- commit
- e463586
- parent
- b2b7ece
- author
- Eric Bower
- date
- 2025-10-11 17:12:34 -0400 EDT
fix: segfault on daemon after existing pty
1 files changed,
+16,
-10
+16,
-10
1@@ -718,6 +718,17 @@ fn renderTerminalSnapshot(session: *Session, allocator: std.mem.Allocator) ![]u8
2 fn notifyAttachedClientsAndCleanup(session: *Session, ctx: *ServerContext, reason: []const u8) void {
3 std.debug.print("Session '{s}' ending: {s}\n", .{ session.name, reason });
4
5+ // Copy the session name before cleanup since HashMap key points to session.name
6+ const session_name = ctx.allocator.dupe(u8, session.name) catch {
7+ // Fallback: just use the existing name and skip removal if allocation fails
8+ std.debug.print("Failed to allocate session name copy\n", .{});
9+ posix.close(session.pty_master_fd);
10+ session.deinit();
11+ ctx.allocator.destroy(session);
12+ return;
13+ };
14+ defer ctx.allocator.free(session_name);
15+
16 // Notify all attached clients
17 var it = session.attached_clients.keyIterator();
18 while (it.next()) |client_fd| {
19@@ -726,24 +737,19 @@ fn notifyAttachedClientsAndCleanup(session: *Session, ctx: *ServerContext, reaso
20 client.allocator,
21 client.fd,
22 .kill_notification,
23- protocol.KillNotification{ .session_name = session.name },
24+ protocol.KillNotification{ .session_name = session_name },
25 ) catch |err| {
26 std.debug.print("Failed to notify client {d}: {s}\n", .{ client_fd.*, @errorName(err) });
27 };
28- // Clear client's attached session reference
29- if (client.attached_session) |attached| {
30- client.allocator.free(attached);
31- client.attached_session = null;
32- }
33+ // Clear client's attached session reference (just null it, don't free - it points to session.name)
34+ client.attached_session = null;
35 }
36
37 // Close PTY master fd
38 posix.close(session.pty_master_fd);
39
40- // Remove from sessions map BEFORE cleaning up (session.deinit frees session.name)
41- const session_name_copy = ctx.allocator.dupe(u8, session.name) catch return;
42- defer ctx.allocator.free(session_name_copy);
43- _ = ctx.sessions.remove(session_name_copy);
44+ // Remove from sessions map BEFORE session.deinit frees the key
45+ _ = ctx.sessions.remove(session_name);
46
47 // Clean up session
48 session.deinit();