1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-11 02:13:56 +09:00
ladybird/Libraries/LibCore
stasoid 17fcbce324 LibCore: Make single-shot timer objects manually reset on Windows
This fixes a really nasty EventLoop bug which I debugged for 2 weeks.

The spin_until([&]{return completed_tasks == total_tasks;}) in
TraversableNavigable::check_if_unloading_is_canceled spins forever.

Cause of the bug:

check_if_unloading_is_canceled is called deferred

check_if_unloading_is_canceled creates a task:

        queue_global_task(..., [&] {
            ...
            completed_tasks++;
        }));

This task is never executed.

queue_global_task calls TaskQueue::add

void TaskQueue::add(task)
{
    m_tasks.append(task);
    m_event_loop->schedule();
}

void HTML::EventLoop::schedule()
{
    if (!m_system_event_loop_timer)
        m_system_event_loop_timer = Timer::create_single_shot(
            0, // delay
            [&] { process(); });

    if (!m_system_event_loop_timer->is_active())
        m_system_event_loop_timer->restart();
}

EventLoop::process executes one task from task queue and calls
schedule again if there are more tasks.

So task processing relies on one single-shot zero-delay timer,
m_system_event_loop_timer.

Timers and other notification events are handled by Core::EventLoop
and Core::ThreadEventQueue, these are different from HTML::EventLoop
and HTML::TaskQueue mentioned above.

check_if_unloading_is_canceled is called using deferred_invoke
mechanism, different from m_system_event_loop_timer,
see Navigable::navigate and Core::EventLoop::deferred_invoke.

The core of the problem is that Core::EventLoop::pump is called again
(from spin_until) after timer fired but before its handler is executed.

In ThreadEventQueue::process events are moved into local variable before
executing. The first of those events is check_if_unloading_is_canceled.
One of the rest events is Web::HTML::EventLoop::process sheduled in
EventLoop::schedule using m_system_event_loop_timer.
When check_if_unloading_is_canceled calls queue_global_task its
m_system_event_loop_timer is still active because Timer::timer_event
was not yet called, so the timer is not restarted.
But Timer::timer_event (and hence EventLoop::process) will never execute
because check_if_unloading_is_canceled calls spin_until after
queue_global_task, and EventLoop::process is no longer in
event_queue.m_private->queued_events.

By making a single-shot timer manually-reset we are allowing it to fire
several times. So when spin_until is executed m_system_event_loop_timer
is fired again. Not an ideal solution, but this is the best I could
come up with. This commit makes the behavior match EventLoopImplUnix,
in which single-shot timer can also fire several times.

Adding event_queue.process(); at the start of pump like in EvtLoopImplQt
doesn't fix the problem.

Note: Timer::start calls EventReceiver::start_timer, which calls
EventLoop::register_timer with should_reload always set to true
(single-shot vs periodic are handled in Timer::timer_event instead),
so I use static_cast<Timer&>(object).is_single_shot() instead of
!should_reload.
2025-04-10 19:02:03 -06:00
..
Platform Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
AnonymousBuffer.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
AnonymousBuffer.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
AnonymousBufferWindows.cpp LibCore: Consistently treat file descriptors as handles on Windows 2025-02-05 19:27:47 -07:00
ArgsParser.cpp LibCore+LibJS+LibWasm: Always use a real format string 2025-04-08 20:00:18 -04:00
ArgsParser.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
CMakeLists.txt Meta+LibCore: Stop linking against LibCrypt 2025-04-08 09:13:33 +02:00
Command.cpp Everywhere: Run clang-format 2024-12-28 05:39:32 -08:00
Command.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
ConfigFile.cpp LibCore: Fix ConfigFile.cpp compilation on Windows 2024-11-19 22:07:01 -07:00
ConfigFile.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
DateTime.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
DateTime.h Everywhere: Remove sv suffix from format string literals 2025-04-08 20:00:18 -04:00
DeferredInvocationContext.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Directory.cpp LibCore: Port Directory to Windows 2024-11-19 22:07:01 -07:00
Directory.h LibCore: Port Directory to Windows 2024-11-19 22:07:01 -07:00
DirectoryEntry.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
DirectoryEntry.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
DirIterator.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
DirIterator.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
ElapsedTimer.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
ElapsedTimer.h LibCore: Remove deprecated ElapsedTimer::elapsed() 2024-11-23 19:20:03 +01:00
Environment.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Environment.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Event.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Event.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
EventLoop.cpp LibCore: Remove unused methods from EventLoop 2025-01-30 15:34:02 -07:00
EventLoop.h LibCore: Add swift bindings for EventLoop as an Executor and Actor 2025-03-15 21:51:22 -06:00
EventLoopExecutor.swift LibCore: Add swift bindings for EventLoop as an Executor and Actor 2025-03-15 21:51:22 -06:00
EventLoopImplementation.cpp LibCore: Port EventLoop to Windows 2024-11-14 11:18:38 -07:00
EventLoopImplementation.h LibCore: Remove unused methods from EventLoop 2025-01-30 15:34:02 -07:00
EventLoopImplementationUnix.cpp LibCore: Remove unused methods from EventLoop 2025-01-30 15:34:02 -07:00
EventLoopImplementationUnix.h LibCore: Remove unused methods from EventLoop 2025-01-30 15:34:02 -07:00
EventLoopImplementationWindows.cpp LibCore: Make single-shot timer objects manually reset on Windows 2025-04-10 19:02:03 -06:00
EventLoopImplementationWindows.h LibCore: Remove unused methods from EventLoop 2025-01-30 15:34:02 -07:00
EventReceiver.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
EventReceiver.h LibCore: Make EventReceiver ref counting use atomics 2024-12-26 13:45:10 +01:00
EventSwift.h LibCore: Add swift bindings for EventLoop as an Executor and Actor 2025-03-15 21:51:22 -06:00
EventSwift.mm LibCore+Meta: Un-break Swift build on Linux 2025-03-18 17:15:08 -06:00
File.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
File.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
FileWatcher.h Everywhere: Include HashMap only where it's actually used 2024-12-09 12:31:16 +01:00
FileWatcherLinux.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
FileWatcherMacOS.mm AK+Everywhere: Rename verify_cast to as 2025-01-21 11:34:06 -05:00
FileWatcherUnimplemented.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Forward.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
IOSurface.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
IOSurface.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
LocalServer.cpp LibCore: Remove SessionManagement utilities 2024-11-26 11:00:48 +01:00
LocalServer.h LibCore: Remove SessionManagement utilities 2024-11-26 11:00:48 +01:00
MachPort.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
MachPort.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
MappedFile.cpp LibCore: Port MappedFile to Windows 2024-11-26 10:00:11 +01:00
MappedFile.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
MimeData.cpp Everywhere: Remove some use of the URL constructors 2025-02-19 08:01:35 -05:00
MimeData.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
NetworkResponse.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Notifier.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Notifier.h LibCore: Fix pthread-related errors on Windows 2024-11-29 10:50:00 +01:00
Process.cpp Everywhere: Run clang-format 2024-12-28 05:39:32 -08:00
Process.h LibCore: Implement System::current_executable_path on Windows 2025-03-19 20:25:24 -06:00
ProcessWindows.cpp LibCore: Correctly pass arguments with spaces to Process on Windows 2025-02-06 15:15:16 -07:00
Promise.h LibCore: Mark the lambda in Promise::when_resolved as mutable 2025-03-09 11:14:20 -04:00
Proxy.h LibURL: Replace Host's Empty state with making Url's Host optional 2024-11-30 12:07:39 +01:00
Resource.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Resource.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
ResourceImplementation.cpp LibCore: Add S_ISDIR, S_ISREG to System.h on Windows 2025-02-12 18:42:05 -07:00
ResourceImplementation.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
ResourceImplementationFile.cpp LibCore: Add S_ISDIR, S_ISREG to System.h on Windows 2025-02-12 18:42:05 -07:00
ResourceImplementationFile.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
SharedCircularQueue.h LibCore: Port SharedCircularQueue to Windows 2024-12-08 17:25:40 -07:00
Socket.cpp LibCore: Implement System::set_close_on_exec 2025-03-19 20:25:24 -06:00
Socket.h LibCore: Don't discard subsequent results in Socket::resolve_host 2025-02-28 15:14:35 +01:00
SocketAddress.h AK+Meta+LibCore+Tests: Remove unused SipHash implementation 2025-04-06 01:47:50 +02:00
SocketAddressWindows.h LibCore: Implement System::socketpair on Windows 2025-02-14 09:38:59 -07:00
SocketpairWindows.cpp LibCore: Implement System::socketpair on Windows 2025-02-14 09:38:59 -07:00
SocketWindows.cpp LibCore: Implement System::set_close_on_exec 2025-03-19 20:25:24 -06:00
StandardPaths.cpp Everywhere: Remove sv suffix from format string literals 2025-04-08 20:00:18 -04:00
StandardPaths.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
System.cpp LibCore: Implement System::set_close_on_exec 2025-03-19 20:25:24 -06:00
System.h LibCore: Implement System::set_close_on_exec 2025-03-19 20:25:24 -06:00
SystemServerTakeover.cpp LibCore: Port SystemServerTakeover.cpp to Windows 2025-02-06 15:25:14 -07:00
SystemServerTakeover.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
SystemWindows.cpp LibCore: Implement System::set_close_on_exec 2025-03-19 20:25:24 -06:00
TCPServer.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
TCPServer.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
ThreadedPromise.h Everywhere: Run clang-format 2024-12-28 05:39:32 -08:00
ThreadEventQueue.cpp LibCore: Don't reserve 2 KiB of stack memory when processing event queue 2024-11-10 19:12:59 +01:00
ThreadEventQueue.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Timer.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Timer.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
TimeZoneWatcher.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
TimeZoneWatcherLinux.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
TimeZoneWatcherMacOS.mm Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
TimeZoneWatcherUnimplemented.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
UDPServer.cpp Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
UDPServer.h Everywhere: Hoist the Libraries folder to the top-level 2024-11-10 12:50:45 +01:00
Version.cpp LibCore: Remove ErrorOr return type from read_long_version_string 2025-02-13 08:27:02 -05:00
Version.h LibCore: Remove ErrorOr return type from read_long_version_string 2025-02-13 08:27:02 -05:00