Re: epoll design problems with common fork/exec patterns

Eric Dumazet
2007-10-27T10:24:17Z

Marc Lehmann a écrit :
> On Sat, Oct 27, 2007 at 11:22:25AM +0200, Eric Dumazet <dada1@cosmosbay.com> wrote:
>
>> If such a bug exists on your kernel, please fill a complete bug report,
>> giving details.
>
> As this behaviour is clearly documented in the epoll manpage, why do you
> think it is a bug? I think its fairly bad, but at least tis documented as
> the behaviour it should be:
>
> Q6 Will the close of an fd cause it to be removed from all epoll sets automatically?
> A6 Yes.

Answer : epoll documentation cannot explain the full semantic of file
descriptors, or difference between user side (file descriptors) and kernel
side (files and fds)
Or should, since you had problems. But then, if the epoll documentation has to
document the full Unix/Linux files semantic, nobody will read it.

The 'close' of a file is not close(fd) :)
But : the last close() so that underlying file refcount is 0

example 1)

fd = open("somefile", ...)
fd1 = dup(fd);
epoll_add_in_my_set(fd1);/* setup epoll work on fd1 */
{do_something;}
close(fd1); /* this is not the last close and will NOT close 'somefile' */
/* It wont be removed from epoll sets NOW */

close(fd); /* oh yes, this one is the real 'file close', now we perform epoll
cleanups */

epoll has to deal with files, but documentation is a User side documentation,
so has to use 'file descriptors'. So everything that plays with the file
descriptor table can make the thing complex to understand/document.
(fork()/dup()/close()/exit()/exec()....)

example 2)

int pfd[2];
pipe(pfd);
epoll_add_in_my_set(pfd[0]);/* setup epoll work on pfd[0] for example */
pid = fork();
if (pid == 0) {

close(pfd[0]); /* this is not the last close and will NOT close pipe */
/* epoll has NO WAY to perform some cleanup at this stage */

close(pfd[1]); /* this not the last close and will NOT close the pipe*/
_exit(0);
}
close(pfd[1]);
wait(NULL);
{do_something_epoll_related;}
close(pfd[0]); /* finally we close the pipe, and epoll can do its cleanup */

fork() is acting sort of dup() , as it increases all file refcounts.

You have problems about close()/dup()/fork()/... file descriptors semantic,
which is handled by a layer independent from epoll stuff.