mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-26 04:02:27 +00:00
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
This commit is contained in:
parent
b8fef58c0c
commit
345fbd1fc1
Notes:
sideshowbarker
2024-07-19 06:37:56 +09:00
Author: https://github.com/bugaevc
Commit: 345fbd1fc1
Pull-request: https://github.com/SerenityOS/serenity/pull/2237
2 changed files with 9 additions and 12 deletions
|
@ -415,14 +415,14 @@ void EventLoop::wait_for_event(WaitMode mode)
|
||||||
timeval now;
|
timeval now;
|
||||||
struct timeval timeout = { 0, 0 };
|
struct timeval timeout = { 0, 0 };
|
||||||
bool should_wait_forever = false;
|
bool should_wait_forever = false;
|
||||||
if (mode == WaitMode::WaitForEvents) {
|
if (mode == WaitMode::WaitForEvents && queued_events_is_empty) {
|
||||||
if (!s_timers->is_empty() && queued_events_is_empty) {
|
auto next_timer_expiration = get_next_timer_expiration();
|
||||||
|
if (next_timer_expiration.has_value()) {
|
||||||
timespec now_spec;
|
timespec now_spec;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now_spec);
|
clock_gettime(CLOCK_MONOTONIC, &now_spec);
|
||||||
now.tv_sec = now_spec.tv_sec;
|
now.tv_sec = now_spec.tv_sec;
|
||||||
now.tv_usec = now_spec.tv_nsec / 1000;
|
now.tv_usec = now_spec.tv_nsec / 1000;
|
||||||
get_next_timer_expiration(timeout);
|
timeval_sub(next_timer_expiration.value(), now, timeout);
|
||||||
timeval_sub(timeout, now, timeout);
|
|
||||||
if (timeout.tv_sec < 0) {
|
if (timeout.tv_sec < 0) {
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
|
@ -430,8 +430,6 @@ void EventLoop::wait_for_event(WaitMode mode)
|
||||||
} else {
|
} else {
|
||||||
should_wait_forever = true;
|
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);
|
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;
|
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());
|
Optional<struct timeval> soonest {};
|
||||||
bool has_checked_any = false;
|
|
||||||
for (auto& it : *s_timers) {
|
for (auto& it : *s_timers) {
|
||||||
auto& fire_time = it.value->fire_time;
|
auto& fire_time = it.value->fire_time;
|
||||||
if (it.value->fire_when_not_visible == TimerShouldFireWhenNotVisible::No
|
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()) {
|
&& !it.value->owner->is_visible_for_timer_purposes()) {
|
||||||
continue;
|
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;
|
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)
|
int EventLoop::register_timer(Object& object, int milliseconds, bool should_reload, TimerShouldFireWhenNotVisible fire_when_not_visible)
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void wait_for_event(WaitMode);
|
void wait_for_event(WaitMode);
|
||||||
void get_next_timer_expiration(timeval&);
|
Optional<struct timeval> get_next_timer_expiration();
|
||||||
|
|
||||||
struct QueuedEvent {
|
struct QueuedEvent {
|
||||||
AK_MAKE_NONCOPYABLE(QueuedEvent);
|
AK_MAKE_NONCOPYABLE(QueuedEvent);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue