[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