On 10/19/2010 10:19 PM, Gustavo Sverzut Barbieri wrote:
On Tue, Oct 19, 2010 at 11:16 AM, Mike McCormack
<[email protected]> wrote:
Hi Guys,
Superficially tested... issue is if somebody does:
close(fd);
ecore_main_fd_handler_del(fdh);
epoll can't remove the fd because it's already closed, so we get an EBADF
from the kernel.
Work around the broken case by issuing a WARN() and reinitializing ecore.
WARN takes no trailing \n
Ack.
other than that, why do we need to reinit it? Just let the fdh handle
be removed from the list and never be considered anymore. I don't see
why we need to reinit it.
Because the fd *may* still be in the epoll array. If somebody happened
to dup() that fd, then the kernel will still have a filp hanging around
and the fd will not be automatically removed from the epoll set. The
kernel only automatically removes an fd from epoll when its filp is
destroyed, not when the fd (which is just a reference to the filp) is
closed.
See the attached program for details. Kernel guys are aware of this,
and say that it works as designed...
thanks,
Mike
/*
* This program demonstrates the following problem with epoll:
*
* epoll refers to fds, but close only removes an fd from epoll
* if there are no other references to the filp
*
* After dup'ing the fd, adding it to epoll and then closing it,
* there is no way to remove it from epoll's fd set any more...
*
* Build with: gcc -Wall -o epoll_dup epoll_dup.c
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
static inline void die(int line, const char *str)
{
fprintf(stderr, "%d %s %d\n", line, str, errno);
exit(1);
}
#define DIE(str) die(__LINE__, str)
int main(int argc, char **argv)
{
struct epoll_event ev = {0};
int r, con, con2, efd;
int count = 1;
/* open something pollable */
printf("open console\n");
con = open("/dev/tty", O_RDWR);
if (con < 0)
DIE("open");
efd = epoll_create(1);
if (efd < 0)
DIE("epoll_create");
printf("dup console\n");
con2 = dup(con);
ev.events = EPOLLIN;
ev.data.ptr = &main;
r = epoll_ctl(efd, EPOLL_CTL_ADD, con, &ev);
if (r < 0)
DIE("epoll_ctl");
r = close(con);
if (r < 0)
DIE("close");
/*
* fd is now in epoll, but close didn't tell epoll that it's gone
* because there's still a filp around with another fd pointing to it
*/
/* can't remove it by it's old fd handle */
ev.events = EPOLLIN;
ev.data.ptr = &main;
r = epoll_ctl(efd, EPOLL_CTL_DEL, con, &ev);
if (r < 0)
fprintf(stderr, "can't remove closed fd... (%d)\n", errno);
/* can't remove it by the dup'ed handle */
ev.events = EPOLLIN;
ev.data.ptr = &main;
r = epoll_ctl(efd, EPOLL_CTL_DEL, con2, &ev);
if (r < 0)
fprintf(stderr, "can't remove dup'ed fd... (%d)\n", errno);
/* but it still works */
printf("press enter\n");
while (count--) {
unsigned char ch;
r = epoll_wait(efd, &ev, 1, -1);
if (r < 0)
DIE("fail");
fprintf(stderr, "epoll ret = %d event = %08x data=%p\n", r, ev.events, ev.data.ptr);
read(con2, &ch, 1);
}
close(efd);
close(con2);
return 0;
}
------------------------------------------------------------------------------
Download new Adobe(R) Flash(R) Builder(TM) 4
The new Adobe(R) Flex(R) 4 and Flash(R) Builder(TM) 4 (formerly
Flex(R) Builder(TM)) enable the development of rich applications that run
across multiple browsers and platforms. Download your free trials today!
http://p.sf.net/sfu/adobe-dev2dev
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel