Hi,
The  EVBACKEND_EPOLL part of  libev manual  said:
           The biggest issue is fork races, however - if
            a program forks then *both* parent and child process have to
            recreate the epoll set, which can take considerable time (one
            syscall per file descriptor) and is of course hard to detect.

I want to know why?

After did some google, this site said, if the child close fds, it will lead
the fds clear form the epoll set in the parents.
https://lkml.org/lkml/2007/10/27/25

But my example code show that closing fds in child wouldn't clear the
parents epoll set.

So I want to know why the parents and child should has to recreate the
epoll set after fork.
Thank you.

this is my example code:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<netdb.h>
#include<fcntl.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/un.h>
#include<netinet/in.h>
#include<netinet/in.h>
#include<netinet/tcp.h>
#include<arpa/inet.h>
#include<sys/epoll.h>


int StartTCPListener(const char* ip, const char* port)
{
    int server_sockfd;
    socklen_t server_len;
    struct sockaddr_in server_address;
    int flag;
    int reuse = 1;

    server_sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(server_sockfd==-1) return -1;
    setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = inet_addr(ip);
    server_address.sin_port = htons(atoi(port));
    server_len = sizeof(server_address);
    if( bind(server_sockfd,(struct sockaddr*)&server_address,server_len) )
return -1;
    if( listen(server_sockfd,SOMAXCONN) ) return -1;
    flag = fcntl(server_sockfd,F_GETFL);
    fcntl(server_sockfd,F_SETFL,flag|O_NONBLOCK);
    fcntl(server_sockfd, F_SETFD, FD_CLOEXEC);
    return server_sockfd;
}

int AcceptTCP(int server_fd)
{
    int client_fd;
    socklen_t client_len;
    struct sockaddr_in client_address;
    client_len = sizeof(client_address);
    int flag;

    client_fd = accept(server_fd,(struct sockaddr
*)&client_address,&client_len);
    if(client_fd>0)
    {
        flag = fcntl(client_fd,F_GETFL);
        fcntl(client_fd,F_SETFL,flag|O_NONBLOCK|O_DSYNC);
        fcntl(client_fd, F_SETFD, FD_CLOEXEC);
    }
    return client_fd;
}

static int AddToEpollSet (int efd, int fd, int events)
{
    struct epoll_event e;
    memset(&e, 0, sizeof(e));
    e.events = events;
    e.data.fd = fd;
    if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &e) == -1)
    {
        int err = errno;
        fprintf(stderr, "epoll_ctl(ADD) failed : %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

int main(const int argc,const char* argv[])
{
    int cpid;
    int efd;
    int sfd = StartTCPListener(argv[1],argv[2]);
    struct epoll_event listener_evetn;
    int n;
    int cfd;
    const char *msg="Hello world!\n";

    if(sfd<0)
    {
        fprintf(stderr,"set socket listening error : %s\n",strerror(errno));
        return -1;
    }
    efd=epoll_create(8);
    if(efd<0)
    {
        fprintf(stderr,"epoll_create error : %s\n",strerror(errno));
        return -1;
    }
    if(AddToEpollSet(efd,sfd,EPOLLIN)<0)
    {
        fprintf(stderr,"add socket to epoll set error :
%s\n",strerror(errno));
        return -1;
    }

    cpid=fork();
    if(cpid<0)
    {
        fprintf(stderr,"fork error : %s\n",strerror(errno));
        return -1;
    }
    if(cpid==0)
    {
        printf("child progress %d\n",getpid());
        close(sfd);
        exit(0);
    }
    waitpid(cpid,NULL,0);
    printf("%d fork %d\n",getpid(),cpid);
    n=epoll_wait(efd,&listener_evetn,1,-1);
    if(n>0)
    {
        if(listener_evetn.events & EPOLLIN)
        {
            cfd=AcceptTCP(listener_evetn.data.fd);
            if(cfd>0)
            {
                write(cfd,msg,strlen(msg));
                close(cfd);
            }
        }
    }
    close(sfd);
    close(efd);
}
_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/mailman/listinfo/libev

Reply via email to