diff options
author | Sergey Bugaev <bugaevc@serenityos.org> | 2020-05-15 18:21:40 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-15 17:41:54 +0200 |
commit | 345fbd1fc1ecffbe6e0d9849373f7af3cbf44a23 (patch) | |
tree | f88834a60248398a754b5ffce1983c5f985185c6 /Libraries/LibCore | |
parent | b8fef58c0c5db8f8a22667c846fa1a8ff8d5d5e1 (diff) | |
download | serenity-345fbd1fc1ecffbe6e0d9849373f7af3cbf44a23.zip |
LibCore: Fix timer expiration processing
The previous code did not account for the case when there are timers present,
but none are enabled, and used a zero polling timeout.
Fixes https://github.com/SerenityOS/serenity/issues/2222
Diffstat (limited to 'Libraries/LibCore')
-rw-r--r-- | Libraries/LibCore/EventLoop.cpp | 19 | ||||
-rw-r--r-- | Libraries/LibCore/EventLoop.h | 2 |
2 files changed, 9 insertions, 12 deletions
diff --git a/Libraries/LibCore/EventLoop.cpp b/Libraries/LibCore/EventLoop.cpp index 272ca0b1d4..ca745468e0 100644 --- a/Libraries/LibCore/EventLoop.cpp +++ b/Libraries/LibCore/EventLoop.cpp @@ -415,14 +415,14 @@ void EventLoop::wait_for_event(WaitMode mode) timeval now; struct timeval timeout = { 0, 0 }; bool should_wait_forever = false; - if (mode == WaitMode::WaitForEvents) { - if (!s_timers->is_empty() && queued_events_is_empty) { + if (mode == WaitMode::WaitForEvents && queued_events_is_empty) { + auto next_timer_expiration = get_next_timer_expiration(); + if (next_timer_expiration.has_value()) { timespec now_spec; clock_gettime(CLOCK_MONOTONIC, &now_spec); now.tv_sec = now_spec.tv_sec; now.tv_usec = now_spec.tv_nsec / 1000; - get_next_timer_expiration(timeout); - timeval_sub(timeout, now, timeout); + timeval_sub(next_timer_expiration.value(), now, timeout); if (timeout.tv_sec < 0) { timeout.tv_sec = 0; timeout.tv_usec = 0; @@ -430,8 +430,6 @@ void EventLoop::wait_for_event(WaitMode mode) } else { should_wait_forever = true; } - } else { - should_wait_forever = false; } int marked_fd_count = Core::safe_syscall(select, max_fd + 1, &rfds, &wfds, nullptr, should_wait_forever ? nullptr : &timeout); @@ -500,10 +498,9 @@ void EventLoopTimer::reload(const timeval& now) fire_time.tv_usec += (interval % 1000) * 1000; } -void EventLoop::get_next_timer_expiration(timeval& soonest) +Optional<struct timeval> EventLoop::get_next_timer_expiration() { - ASSERT(!s_timers->is_empty()); - bool has_checked_any = false; + Optional<struct timeval> soonest {}; for (auto& it : *s_timers) { auto& fire_time = it.value->fire_time; if (it.value->fire_when_not_visible == TimerShouldFireWhenNotVisible::No @@ -511,10 +508,10 @@ void EventLoop::get_next_timer_expiration(timeval& soonest) && !it.value->owner->is_visible_for_timer_purposes()) { continue; } - if (!has_checked_any || fire_time.tv_sec < soonest.tv_sec || (fire_time.tv_sec == soonest.tv_sec && fire_time.tv_usec < soonest.tv_usec)) + if (!soonest.has_value() || fire_time.tv_sec < soonest.value().tv_sec || (fire_time.tv_sec == soonest.value().tv_sec && fire_time.tv_usec < soonest.value().tv_usec)) soonest = fire_time; - has_checked_any = true; } + return soonest; } int EventLoop::register_timer(Object& object, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible fire_when_not_visible) diff --git a/Libraries/LibCore/EventLoop.h b/Libraries/LibCore/EventLoop.h index e1f4891ba6..b122bdf860 100644 --- a/Libraries/LibCore/EventLoop.h +++ b/Libraries/LibCore/EventLoop.h @@ -77,7 +77,7 @@ public: private: void wait_for_event(WaitMode); - void get_next_timer_expiration(timeval&); + Optional<struct timeval> get_next_timer_expiration(); struct QueuedEvent { AK_MAKE_NONCOPYABLE(QueuedEvent); |