renderer/termio attach thread local state for crash capture

This commit is contained in:
Mitchell Hashimoto
2024-09-01 10:59:19 -07:00
parent f0916d58e8
commit 8f477b00da
3 changed files with 19 additions and 10 deletions

View File

@ -29,7 +29,7 @@ pub const ThreadState = struct {
/// See ThreadState. This should only ever be set by the owner of the /// See ThreadState. This should only ever be set by the owner of the
/// thread entry function. /// thread entry function.
threadlocal var thread_state: ?ThreadState = null; pub threadlocal var thread_state: ?ThreadState = null;
/// Process-wide initialization of our Sentry client. /// Process-wide initialization of our Sentry client.
/// ///
@ -140,15 +140,10 @@ fn beforeSend(
// handler to set thread-specific data such as window size, grid size, // handler to set thread-specific data such as window size, grid size,
// etc. that we can use to debug crashes. // etc. that we can use to debug crashes.
const thr_state = thread_state orelse { // If we don't have thread state we can't reliably determine
// If we don't have thread state we note this in the context // metadata such as surface dimensions. In the future we can probably
// so we can see that but don't do anything else. // drop full app state (all surfaces, all windows, etc.).
const obj = sentry.Value.initObject(); const thr_state = thread_state orelse return event_val;
errdefer obj.decref();
obj.setByKey("unknown", sentry.Value.initBool(true));
sentry.setContext("surface", obj);
return event_val;
};
// Read the surface data. This is likely unsafe because on a crash // Read the surface data. This is likely unsafe because on a crash
// other threads can continue running. We don't have race-safe way to // other threads can continue running. We don't have race-safe way to

View File

@ -5,6 +5,7 @@ pub const Thread = @This();
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const xev = @import("xev"); const xev = @import("xev");
const crash = @import("../crash/main.zig");
const renderer = @import("../renderer.zig"); const renderer = @import("../renderer.zig");
const apprt = @import("../apprt.zig"); const apprt = @import("../apprt.zig");
const configpkg = @import("../config.zig"); const configpkg = @import("../config.zig");
@ -191,6 +192,12 @@ pub fn threadMain(self: *Thread) void {
fn threadMain_(self: *Thread) !void { fn threadMain_(self: *Thread) !void {
defer log.debug("renderer thread exited", .{}); defer log.debug("renderer thread exited", .{});
// Setup our crash metadata
crash.sentry.thread_state = .{
.surface = self.renderer.surface_mailbox.surface,
};
defer crash.sentry.thread_state = null;
// Run our loop start/end callbacks if the renderer cares. // Run our loop start/end callbacks if the renderer cares.
const has_loop = @hasDecl(renderer.Renderer, "loopEnter"); const has_loop = @hasDecl(renderer.Renderer, "loopEnter");
if (has_loop) try self.renderer.loopEnter(self); if (has_loop) try self.renderer.loopEnter(self);

View File

@ -15,6 +15,7 @@ const std = @import("std");
const ArenaAllocator = std.heap.ArenaAllocator; const ArenaAllocator = std.heap.ArenaAllocator;
const builtin = @import("builtin"); const builtin = @import("builtin");
const xev = @import("xev"); const xev = @import("xev");
const crash = @import("../crash/main.zig");
const termio = @import("../termio.zig"); const termio = @import("../termio.zig");
const BlockingQueue = @import("../blocking_queue.zig").BlockingQueue; const BlockingQueue = @import("../blocking_queue.zig").BlockingQueue;
@ -200,6 +201,12 @@ pub fn threadMain(self: *Thread, io: *termio.Termio) void {
fn threadMain_(self: *Thread, io: *termio.Termio) !void { fn threadMain_(self: *Thread, io: *termio.Termio) !void {
defer log.debug("IO thread exited", .{}); defer log.debug("IO thread exited", .{});
// Setup our crash metadata
crash.sentry.thread_state = .{
.surface = io.surface_mailbox.surface,
};
defer crash.sentry.thread_state = null;
// Get the mailbox. This must be an SPSC mailbox for threading. // Get the mailbox. This must be an SPSC mailbox for threading.
const mailbox = switch (io.mailbox) { const mailbox = switch (io.mailbox) {
.spsc => |*v| v, .spsc => |*v| v,