From 2fea9cb179653736340adeb8527d6a56c2a0a9ad Mon Sep 17 00:00:00 2001 From: raster Date: Wed, 20 Oct 2010 14:15:56 +0000 Subject: [PATCH] patch from mike - fix epoll on fork thing. This is an attempt to fix the epoll/fork() issue reported to me where we end up with a single epoll fd shared between two processes after a fork() in E. I've tested with elementary test in epoll and non-epoll combinations, and all appears to be well. Please check it solves the issue you saw, and reformat the code as you see fit... ;-) git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@53670 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- AUTHORS | 1 + configure.ac | 1 + src/lib/ecore/ecore_main.c | 69 +++++++++++++++++++++++------ src/lib/ecore_input_evas/ecore_input_evas.c | 10 ++--- 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/AUTHORS b/AUTHORS index f13ae18..7784236 100644 --- a/AUTHORS +++ b/AUTHORS @@ -35,3 +35,4 @@ Nicolas Aguirre Brett Nash Mike Blumenkrantz Leif Middelschulte +Mike McCormack diff --git a/configure.ac b/configure.ac index c475fb9..f54edad 100644 --- a/configure.ac +++ b/configure.ac @@ -912,6 +912,7 @@ m4_ifdef([AC_PROG_OBJC], [ ]) AC_SUBST(cocoa_ldflags) +want_epoll=yes AC_ARG_ENABLE(epoll, AC_HELP_STRING([--enable-epoll], [enable or disable epoll support]), [want_epoll=$enableval]) diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c index e5e9db0..1b33a19 100644 --- a/src/lib/ecore/ecore_main.c +++ b/src/lib/ecore/ecore_main.c @@ -133,10 +133,13 @@ static double t2 = 0.0; #ifdef HAVE_EPOLL static int epoll_fd = -1; -static GPollFD ecore_epoll_fd; +static pid_t epoll_pid; #endif #ifdef USE_G_MAIN_LOOP +#ifdef HAVE_EPOLL +static GPollFD ecore_epoll_fd; +#endif static GSource *ecore_glib_source; static guint ecore_glib_source_id; static GMainLoop* ecore_main_loop; @@ -146,6 +149,33 @@ static gboolean ecore_fds_ready; #ifdef HAVE_EPOLL static inline int +_ecore_get_epoll_fd(void) +{ + if (epoll_pid && epoll_pid != getpid()) + { + /* forked! */ + _ecore_main_loop_shutdown(); + } + if (epoll_pid == 0 && epoll_fd < 0) + { + _ecore_main_loop_init(); + } + return epoll_fd; +} + +static inline int +_ecore_epoll_add(int efd, int fd, int events, void *ptr) +{ + struct epoll_event ev; + + memset(&ev, 0, sizeof (ev)); + ev.events = events; + ev.data.ptr = ptr; + INF("adding poll on %d %08x", fd, events); + return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev); +} + +static inline int _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh) { int events = 0; @@ -179,13 +209,8 @@ _ecore_main_fdh_poll_add(Ecore_Fd_Handler *fdh) { int r = 0; #ifdef HAVE_EPOLL - struct epoll_event ev; - - memset(&ev, 0, sizeof (ev)); - ev.events = _ecore_poll_events_from_fdh(fdh); - ev.data.ptr = fdh; - INF("adding poll on %d %08x", fdh->fd, ev.events); - r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fdh->fd, &ev); + r = _ecore_epoll_add(_ecore_get_epoll_fd(), fdh->fd, + _ecore_poll_events_from_fdh(fdh), fdh); #elif USE_G_MAIN_LOOP fdh->gfd.fd = fdh->fd; fdh->gfd.events = _gfd_events_from_fdh(fdh); @@ -207,11 +232,12 @@ _ecore_main_fdh_poll_del(Ecore_Fd_Handler *fdh) { #ifdef HAVE_EPOLL struct epoll_event ev; + int efd = _ecore_get_epoll_fd(); memset(&ev, 0, sizeof (ev)); INF("removing poll on %d", fdh->fd); /* could get an EBADF if somebody closed the FD before removing it */ - if ((epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0) && + if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0) && (errno != EBADF)) { ERR("Failed to delete epoll fd %d! (errno=%d)", fdh->fd, errno); @@ -237,12 +263,13 @@ _ecore_main_fdh_poll_modify(Ecore_Fd_Handler *fdh) int r = 0; #ifdef HAVE_EPOLL struct epoll_event ev; + int efd = _ecore_get_epoll_fd(); memset(&ev, 0, sizeof (ev)); ev.events = _ecore_poll_events_from_fdh(fdh); ev.data.ptr = fdh; INF("modifing epoll on %d to %08x", fdh->fd, ev.events); - r = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fdh->fd, &ev); + r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev); #elif USE_G_MAIN_LOOP fdh->gfd.fd = fdh->fd; fdh->gfd.events = _gfd_events_from_fdh(fdh); @@ -263,9 +290,10 @@ static inline int _ecore_main_fdh_poll_mark_active(void) { struct epoll_event ev[32]; int i, ret; + int efd = _ecore_get_epoll_fd(); memset(&ev, 0, sizeof (ev)); - ret = epoll_wait(epoll_fd, ev, sizeof(ev) / sizeof(struct epoll_event), 0); + ret = epoll_wait(efd, ev, sizeof(ev) / sizeof(struct epoll_event), 0); if (ret < 0) { if (errno == EINTR) return -1; @@ -475,6 +503,19 @@ _ecore_main_loop_init(void) epoll_fd = epoll_create(1); if (epoll_fd < 0) CRIT("Failed to create epoll fd!"); + epoll_pid = getpid(); + + /* add polls on all our file descriptors */ + Ecore_Fd_Handler *fdh; + EINA_INLIST_FOREACH(fd_handlers, fdh) + { + if (fdh->delete_me) + continue; + _ecore_epoll_add(epoll_fd, fdh->fd, + _ecore_poll_events_from_fdh(fdh), fdh); + _ecore_main_fdh_poll_add(fdh); + } + #endif #ifdef USE_G_MAIN_LOOP @@ -514,6 +555,8 @@ _ecore_main_loop_shutdown(void) close(epoll_fd); epoll_fd = -1; } + + epoll_pid = 0; #endif } @@ -980,8 +1023,8 @@ _ecore_main_select(double timeout) } #else /* HAVE_EPOLL */ /* polling on the epoll fd will wake when an fd in the epoll set is active */ - FD_SET(epoll_fd, &rfds); - max_fd = epoll_fd; + max_fd = _ecore_get_epoll_fd(); + FD_SET(max_fd, &rfds); #endif /* HAVE_EPOLL */ if (_ecore_signal_count_get()) return -1; diff --git a/src/lib/ecore_input_evas/ecore_input_evas.c b/src/lib/ecore_input_evas/ecore_input_evas.c index 4de8b1d..174d540 100644 --- a/src/lib/ecore_input_evas/ecore_input_evas.c +++ b/src/lib/ecore_input_evas/ecore_input_evas.c @@ -132,7 +132,7 @@ _ecore_event_evas_key(Ecore_Event_Key *e, Ecore_Event_Press press) { Ecore_Input_Window *lookup; - lookup = _ecore_event_window_match(e->event_window); + lookup = _ecore_event_window_match(e->window); if (!lookup) return ECORE_CALLBACK_RENEW; ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers); if (press == ECORE_DOWN) @@ -148,7 +148,7 @@ _ecore_event_evas_mouse_button(Ecore_Event_Mouse_Button *e, Ecore_Event_Press pr Ecore_Input_Window *lookup; Evas_Button_Flags flags = EVAS_BUTTON_NONE; - lookup = _ecore_event_window_match(e->event_window); + lookup = _ecore_event_window_match(e->window); if (!lookup) return ECORE_CALLBACK_RENEW; if (e->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK; if (e->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK; @@ -177,7 +177,7 @@ ecore_event_evas_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *ev Ecore_Input_Window *lookup; e = event; - lookup = _ecore_event_window_match(e->event_window); + lookup = _ecore_event_window_match(e->window); if (!lookup) return ECORE_CALLBACK_RENEW; if (e->multi.device == 0) { @@ -208,7 +208,7 @@ _ecore_event_evas_mouse_io(Ecore_Event_Mouse_IO *e, Ecore_Event_IO io) { Ecore_Input_Window *lookup; - lookup = _ecore_event_window_match(e->event_window); + lookup = _ecore_event_window_match(e->window); if (!lookup) return ECORE_CALLBACK_RENEW; ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers); switch (io) @@ -246,7 +246,7 @@ ecore_event_evas_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *e Ecore_Input_Window *lookup; e = event; - lookup = _ecore_event_window_match(e->event_window); + lookup = _ecore_event_window_match(e->window); if (!lookup) return ECORE_CALLBACK_RENEW; ecore_event_evas_modifier_lock_update(lookup->evas, e->modifiers); evas_event_feed_mouse_wheel(lookup->evas, e->direction, e->z, e->timestamp, NULL); -- 2.7.4