Try fixing segfault by not being as aggressive with freeing Persisted Resolvers

This commit is contained in:
Karl Seguin
2025-09-17 20:14:13 +08:00
parent 4d1e416299
commit afa0d5ba12
4 changed files with 15 additions and 11 deletions

View File

@@ -101,7 +101,7 @@ pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promi
try page.requestCookie(.{}).headersForRequest(arena, req.url, &headers); try page.requestCookie(.{}).headersForRequest(arena, req.url, &headers);
const resolver = page.main_context.createPersistentPromiseResolver(); const resolver = try page.main_context.createPersistentPromiseResolver();
const fetch_ctx = try arena.create(FetchContext); const fetch_ctx = try arena.create(FetchContext);
fetch_ctx.* = .{ fetch_ctx.* = .{
@@ -170,7 +170,6 @@ pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promi
.done_callback = struct { .done_callback = struct {
fn doneCallback(ctx: *anyopaque) !void { fn doneCallback(ctx: *anyopaque) !void {
const self: *FetchContext = @ptrCast(@alignCast(ctx)); const self: *FetchContext = @ptrCast(@alignCast(ctx));
defer self.promise_resolver.deinit();
self.transfer = null; self.transfer = null;
log.info(.fetch, "request complete", .{ log.info(.fetch, "request complete", .{
@@ -187,7 +186,6 @@ pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promi
.error_callback = struct { .error_callback = struct {
fn errorCallback(ctx: *anyopaque, err: anyerror) void { fn errorCallback(ctx: *anyopaque, err: anyerror) void {
const self: *FetchContext = @ptrCast(@alignCast(ctx)); const self: *FetchContext = @ptrCast(@alignCast(ctx));
defer self.promise_resolver.deinit();
self.transfer = null; self.transfer = null;
log.err(.fetch, "error", .{ log.err(.fetch, "error", .{

View File

@@ -78,8 +78,8 @@ const QueueingStrategy = struct {
pub fn constructor(underlying: ?UnderlyingSource, _strategy: ?QueueingStrategy, page: *Page) !*ReadableStream { pub fn constructor(underlying: ?UnderlyingSource, _strategy: ?QueueingStrategy, page: *Page) !*ReadableStream {
const strategy: QueueingStrategy = _strategy orelse .{}; const strategy: QueueingStrategy = _strategy orelse .{};
const cancel_resolver = page.main_context.createPersistentPromiseResolver(); const cancel_resolver = try page.main_context.createPersistentPromiseResolver();
const closed_resolver = page.main_context.createPersistentPromiseResolver(); const closed_resolver = try page.main_context.createPersistentPromiseResolver();
const stream = try page.arena.create(ReadableStream); const stream = try page.arena.create(ReadableStream);
stream.* = ReadableStream{ .cancel_resolver = cancel_resolver, .closed_resolver = closed_resolver, .strategy = strategy }; stream.* = ReadableStream{ .cancel_resolver = cancel_resolver, .closed_resolver = closed_resolver, .strategy = strategy };
@@ -106,9 +106,6 @@ pub fn constructor(underlying: ?UnderlyingSource, _strategy: ?QueueingStrategy,
} }
pub fn destructor(self: *ReadableStream) void { pub fn destructor(self: *ReadableStream) void {
self.cancel_resolver.deinit();
self.closed_resolver.deinit();
if (self.reader_resolver) |*rr| { if (self.reader_resolver) |*rr| {
rr.deinit(); rr.deinit();
} }

View File

@@ -56,7 +56,7 @@ pub fn _read(self: *const ReadableStreamDefaultReader, page: *Page) !Env.Promise
if (self.stream.reader_resolver) |rr| { if (self.stream.reader_resolver) |rr| {
return rr.promise(); return rr.promise();
} else { } else {
const persistent_resolver = page.main_context.createPersistentPromiseResolver(); const persistent_resolver = try page.main_context.createPersistentPromiseResolver();
self.stream.reader_resolver = persistent_resolver; self.stream.reader_resolver = persistent_resolver;
return persistent_resolver.promise(); return persistent_resolver.promise();
} }

View File

@@ -677,6 +677,9 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
// we now simply persist every time persist() is called. // we now simply persist every time persist() is called.
js_object_list: std.ArrayListUnmanaged(PersistentObject) = .empty, js_object_list: std.ArrayListUnmanaged(PersistentObject) = .empty,
persisted_promise_resolvers: std.ArrayListUnmanaged(v8.Persistent(v8.PromiseResolver)) = .empty,
// When we need to load a resource (i.e. an external script), we call // When we need to load a resource (i.e. an external script), we call
// this function to get the source. This is always a reference to the // this function to get the source. This is always a reference to the
// Page's fetchModuleSource, but we use a function pointer // Page's fetchModuleSource, but we use a function pointer
@@ -733,6 +736,10 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
p.deinit(); p.deinit();
} }
for (self.persisted_promise_resolvers.items) |*p| {
p.deinit();
}
{ {
var it = self.module_cache.valueIterator(); var it = self.module_cache.valueIterator();
while (it.next()) |p| { while (it.next()) |p| {
@@ -1261,10 +1268,12 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
}; };
} }
pub fn createPersistentPromiseResolver(self: *JsContext) PersistentPromiseResolver { pub fn createPersistentPromiseResolver(self: *JsContext) !PersistentPromiseResolver {
const resolver = v8.Persistent(v8.PromiseResolver).init(self.isolate, v8.PromiseResolver.init(self.v8_context));
try self.persisted_promise_resolvers.append(self.context_arena, resolver);
return .{ return .{
.js_context = self, .js_context = self,
.resolver = v8.Persistent(v8.PromiseResolver).init(self.isolate, v8.PromiseResolver.init(self.v8_context)), .resolver = resolver,
}; };
} }