Skip to content

Commit ae92ef6

Browse files
committed
don't allow concurrent blocking calls
1 parent 7f70e94 commit ae92ef6

File tree

4 files changed

+36
-29
lines changed

4 files changed

+36
-29
lines changed

src/browser/ScriptManager.zig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ page: *Page,
3838
// used to prevent recursive evalution
3939
is_evaluating: bool,
4040

41+
// used to prevent executing scripts while we're doing a blocking load
42+
is_blocking: bool = false,
43+
4144
// Only once this is true can deferred scripts be run
4245
static_scripts_done: bool,
4346

@@ -54,6 +57,7 @@ deferreds: OrderList,
5457

5558
shutdown: bool = false,
5659

60+
5761
client: *HttpClient,
5862
allocator: Allocator,
5963
buffer_pool: BufferPool,
@@ -269,6 +273,17 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element) !void {
269273
// http handle, these are executed without there necessarily being a free handle.
270274
// Thus, Http/Client.zig maintains a dedicated handle for these calls.
271275
pub fn blockingGet(self: *ScriptManager, url: [:0]const u8) !BlockingResult {
276+
std.debug.assert(self.is_blocking == false);
277+
278+
self.is_blocking = true;
279+
defer {
280+
self.is_blocking = false;
281+
282+
// we blocked evaluation while loading this script, there could be
283+
// scripts ready to process.
284+
self.evaluate();
285+
}
286+
272287
var blocking = Blocking{
273288
.allocator = self.allocator,
274289
.buffer_pool = &self.buffer_pool,
@@ -314,6 +329,13 @@ fn evaluate(self: *ScriptManager) void {
314329
return;
315330
}
316331

332+
if (self.is_blocking) {
333+
// Cannot evaluate scripts while a blocking-load is in progress. Not
334+
// only could that result in incorrect evaluation order, it could
335+
// triger another blocking request, while we're doing a blocking request.
336+
return;
337+
}
338+
317339
const page = self.page;
318340
self.is_evaluating = true;
319341
defer self.is_evaluating = false;

src/browser/session.zig

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,15 @@ pub const Session = struct {
118118

119119
std.debug.assert(self.page != null);
120120

121-
self.page.?.deinit();
122-
self.page = null;
123-
124121
// RemoveJsContext() will execute the destructor of any type that
125122
// registered a destructor (e.g. XMLHttpRequest).
123+
// Should be called before we deinit the page, because these objects
124+
// could be referencing it.
126125
self.executor.removeJsContext();
127126

127+
self.page.?.deinit();
128+
self.page = null;
129+
128130
// clear netsurf memory arena.
129131
parser.deinit();
130132

src/browser/xhr/xhr.zig

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,12 @@ pub const XMLHttpRequest = struct {
171171
};
172172
}
173173

174-
// pub fn destructor(self: *XMLHttpRequest) void {
175-
// if (self.transfer) |transfer| {
176-
// transfer.abort();
177-
// self.transfer = null;
178-
// }
179-
// }
174+
pub fn destructor(self: *XMLHttpRequest) void {
175+
if (self.transfer) |transfer| {
176+
transfer.abort();
177+
self.transfer = null;
178+
}
179+
}
180180

181181
pub fn reset(self: *XMLHttpRequest) void {
182182
self.url = null;

src/http/Client.zig

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,6 @@ transfer_pool: std.heap.MemoryPool(Transfer),
7474
// see ScriptManager.blockingGet
7575
blocking: Handle,
7676

77-
// Boolean to check that we don't make a blocking request while an existing
78-
// blocking request is already being processed.
79-
blocking_active: if (builtin.mode == .Debug) bool else void = if (builtin.mode == .Debug) false else {},
80-
8177
// The only place this is meant to be used is in `makeRequest` BEFORE `perform`
8278
// is called. It is used to generate our Cookie header. It can be used for other
8379
// purposes, but keep in mind that, while single-threaded, calls like makeRequest
@@ -199,14 +195,6 @@ pub fn request(self: *Client, req: Request) !void {
199195

200196
// See ScriptManager.blockingGet
201197
pub fn blockingRequest(self: *Client, req: Request) !void {
202-
if (comptime builtin.mode == .Debug) {
203-
std.debug.assert(self.blocking_active == false);
204-
self.blocking_active = true;
205-
}
206-
defer if (comptime builtin.mode == .Debug) {
207-
self.blocking_active = false;
208-
};
209-
210198
return self.makeRequest(&self.blocking, req);
211199
}
212200

@@ -361,7 +349,7 @@ fn endTransfer(self: *Client, transfer: *Transfer) void {
361349
self.transfer_pool.destroy(transfer);
362350

363351
errorMCheck(c.curl_multi_remove_handle(self.multi, handle.conn.easy)) catch |err| {
364-
log.fatal(.http, "Failed to abort", .{ .err = err });
352+
log.fatal(.http, "Failed to remove handle", .{ .err = err });
365353
};
366354

367355
self.handles.release(handle);
@@ -372,11 +360,6 @@ fn ensureNoActiveConnection(self: *const Client) !void {
372360
if (self.active > 0) {
373361
return error.InflightConnection;
374362
}
375-
if (comptime builtin.mode == .Debug) {
376-
if (self.blocking_active) {
377-
return error.InflightConnection;
378-
}
379-
}
380363
}
381364

382365
const Handles = struct {
@@ -429,8 +412,8 @@ const Handles = struct {
429412
}
430413

431414
fn release(self: *Handles, handle: *Handle) void {
432-
// client.blocking is a handle without a node, it doesn't exist in the
433-
// eitehr the in_use or available lists.
415+
// client.blocking is a handle without a node, it doesn't exist in
416+
// either the in_use or available lists.
434417
const node = &(handle.node orelse return);
435418

436419
self.in_use.remove(node);

0 commit comments

Comments
 (0)