From 2788c36ca690d57384682b6d04e0916eda3486d4 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Thu, 12 Jun 2025 22:34:23 +0800 Subject: [PATCH] Fix loop run (Page.wait) In https://github.com/lightpanda-io/browser/pull/767 I tried to call loop.run from within a loop.run (spoiler, it didn't work), in order to make sure aborted connections were properly cleaned up before starting a new navigation. That resulted in having loop.run no longer wait for timeouts for fear of having to wait on a long timeout. The ended up breaking page.wait (used in the fetch command). This commit brings back the original behavior where loop.run() waits for all completions. Which is now safe to do since the nested loop.run() call has been removed. --- src/runtime/loop.zig | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/runtime/loop.zig b/src/runtime/loop.zig index cd4f1464..6e022e44 100644 --- a/src/runtime/loop.zig +++ b/src/runtime/loop.zig @@ -81,12 +81,13 @@ pub const Loop = struct { // run tail events. We do run the tail events to ensure all the // contexts are correcly free. - while (self.hasPendinEvents()) { - self.io.run_for_ns(10 * std.time.ns_per_ms) catch |err| { + while (self.pending_network_count != 0 or self.pending_timeout_count != 0) { + self.io.run_for_ns(std.time.ns_per_ms * 10) catch |err| { log.err(.loop, "deinit", .{ .err = err }); break; }; } + if (comptime CANCEL_SUPPORTED) { self.io.cancel_all(); } @@ -96,21 +97,6 @@ pub const Loop = struct { self.cancelled.deinit(self.alloc); } - // We can shutdown once all the pending network IO is complete. - // In debug mode we also wait until al the pending timeouts are complete - // but we only do this so that the `timeoutCallback` can free all allocated - // memory and we won't report a leak. - fn hasPendinEvents(self: *const Self) bool { - if (self.pending_network_count > 0) { - return true; - } - - if (builtin.mode != .Debug) { - return false; - } - return self.pending_timeout_count > 0; - } - // Retrieve all registred I/O events completed by OS kernel, // and execute sequentially their callbacks. // Stops when there is no more I/O events registered on the loop. @@ -121,9 +107,11 @@ pub const Loop = struct { self.stopping = true; defer self.stopping = false; - while (self.pending_network_count > 0) { - try self.io.run_for_ns(10 * std.time.ns_per_ms); - // at each iteration we might have new events registred by previous callbacks + while (self.pending_network_count != 0 or self.pending_timeout_count != 0) { + self.io.run_for_ns(std.time.ns_per_ms * 10) catch |err| { + log.err(.loop, "deinit", .{ .err = err }); + break; + }; } }