From 9443868d55a829cd66a2dce24daad84c5f1ca2ed Mon Sep 17 00:00:00 2001 From: Nate Rosenblum Date: Tue, 5 Mar 2013 11:29:33 -0800 Subject: [PATCH] Double-check next timeout when adding events When resuming the system from a suspended state, the ev_timeout field of a scheduled timer event may be in the past. This leads to unexpected behavior when scheduling a short-duration timer event immediately after returning from suspension, because the new event does not land on top of the timeout minheap and so the event loop (blocked on a possibly long-duration timeout) is not notified. This patch checks for this condition and, if it obtains, notifies the event loop. --- event.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/event.c b/event.c index 51e34a99..9286c36f 100644 --- a/event.c +++ b/event.c @@ -2378,12 +2378,18 @@ event_add_nolock_(struct event *ev, const struct timeval *tv, common_timeout_schedule(ctl, &now, ev); } } else { + struct event* top = NULL; /* See if the earliest timeout is now earlier than it * was before: if so, we will need to tell the main - * thread to wake up earlier than it would - * otherwise. */ + * thread to wake up earlier than it would otherwise. + * We double check the timeout of the top element to + * handle time distortions due to system suspension. + */ if (min_heap_elt_is_top_(ev)) notify = 1; + else if ((top = min_heap_top_(&base->timeheap)) != NULL && + evutil_timercmp(&top->ev_timeout, &now, <)) + notify = 1; } } -- 2.40.0