From: Nate Rosenblum Date: Tue, 5 Mar 2013 19:29:33 +0000 (-0800) Subject: Double-check next timeout when adding events X-Git-Tag: release-2.1.3-alpha~37 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9443868d55a829cd66a2dce24daad84c5f1ca2ed;p=libevent 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. --- 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; } }