[PATCH] Reference event sources signalled by epoll before timeout handling.

James Hunt james.hunt at ubuntu.com
Mon Apr 23 01:14:40 PDT 2012


If ply_event_loop_handle_timeouts() is called before the events returned
by epoll_wait() are referenced, a timeout handler can free an event
source leading to undefined behaviour (and frequently SIGSEGV crashes)
once ply_event_loop_handle_timeouts() has finished since
ply_event_loop_process_pending_events() continues to try and process the
now invalid event sources. Thanks to cjwatson for a simpler solution to
my original fix.

Save errno values to ensure logic is robust in case handler makes
system call.
---
 src/libply/ply-event-loop.c |   27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/src/libply/ply-event-loop.c b/src/libply/ply-event-loop.c
index acfdc5d..99f5c46 100644
--- a/src/libply/ply-event-loop.c
+++ b/src/libply/ply-event-loop.c
@@ -1277,8 +1277,7 @@ ply_event_loop_process_pending_events (ply_event_loop_t *loop)
      number_of_received_events = epoll_wait (loop->epoll_fd, events,
                                              PLY_EVENT_LOOP_NUM_EVENT_HANDLERS,
                                              timeout);
-
-     ply_event_loop_handle_timeouts (loop);
+     ply_save_errno ();
 
      if (number_of_received_events < 0)
        {
@@ -1288,19 +1287,23 @@ ply_event_loop_process_pending_events (ply_event_loop_t *loop)
              return;
            }
        }
-    }
-  while ((number_of_received_events < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 
-  /* first reference all sources, so they stay alive for the duration of this
-   * iteration of the loop
-   */
-  for (i = 0; i < number_of_received_events; i++)
-    {
-      ply_event_source_t *source;
-      source = (ply_event_source_t *) (events[i].data.ptr);
+     /* Reference all sources, so they stay alive for the duration of this
+      * iteration of the loop
+      */
+     for (i = 0; i < number_of_received_events; i++)
+       {
+         ply_event_source_t *source;
+         source = (ply_event_source_t *) (events[i].data.ptr);
+
+         ply_event_source_take_reference (source);
+       }
 
-      ply_event_source_take_reference (source);
+     ply_event_loop_handle_timeouts (loop);
+
+     ply_restore_errno ();
     }
+  while ((number_of_received_events < 0) && ((errno == EINTR) || (errno == EAGAIN)));
 
   /* Then process the incoming events
    */
-- 
1.7.9.5


--------------030706090900060008070503--


More information about the plymouth mailing list