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.
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;
}
}