- commit
- 686ee94
- parent
- c2e856c
- author
- Eric Bower
- date
- 2025-11-26 14:50:43 -0500 EST
refactor: cleanup logs
2 files changed,
+30,
-35
+1,
-1
1@@ -62,7 +62,7 @@ pub const LogSystem = struct {
2 self.current_size += total_len;
3
4 var buf: [4096]u8 = undefined;
5- var w = f.writer(&buf);
6+ var w = f.writerStreaming(&buf);
7 w.interface.print(prefix ++ format ++ "\n", prefix_args ++ args) catch {};
8 w.interface.flush() catch {};
9 }
+29,
-34
1@@ -97,12 +97,12 @@ const Daemon = struct {
2 }
3
4 pub fn closeClient(self: *Daemon, client: *Client, i: usize, shutdown_on_last: bool) bool {
5- std.log.info("closing client idx={d}", .{i});
6+ const fd = client.socket_fd;
7 client.deinit();
8 self.alloc.destroy(client);
9 _ = self.clients.orderedRemove(i);
10+ std.log.info("client disconnected fd={d} remaining={d}", .{ fd, self.clients.items.len });
11 if (shutdown_on_last and self.clients.items.len == 0) {
12- std.log.info("last client disconnected, shutting down", .{});
13 self.shutdown();
14 return true;
15 }
16@@ -126,8 +126,6 @@ pub fn main() !void {
17 try log_system.init(alloc, log_path);
18 defer log_system.deinit();
19
20- std.log.info("running cli", .{});
21-
22 const cmd = args.next() orelse {
23 return list(&cfg);
24 };
25@@ -168,11 +166,23 @@ pub fn main() !void {
26 }
27
28 fn help() !void {
29- std.log.info("running cmd=help", .{});
30+ const help_text =
31+ \\zmx - session persistence for terminal processes
32+ \\
33+ \\Usage: zmx <command> [args]
34+ \\
35+ \\Commands:
36+ \\ attach <name> Create or attach to a session
37+ \\ detach Detach from current session (or Ctrl+\)
38+ \\ list List active sessions
39+ \\ kill <name> Kill a session and all attached clients
40+ \\ help Show this help message
41+ \\
42+ ;
43+ try std.fs.File.stdout().writeAll(help_text);
44 }
45
46 fn list(cfg: *Cfg) !void {
47- std.log.info("running cmd=list", .{});
48 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
49 defer _ = gpa.deinit();
50 const alloc = gpa.allocator();
51@@ -236,7 +246,6 @@ fn list(cfg: *Cfg) !void {
52 }
53
54 fn detachAll(cfg: *Cfg) !void {
55- std.log.info("running cmd=detach", .{});
56 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
57 defer _ = gpa.deinit();
58 const alloc = gpa.allocator();
59@@ -260,7 +269,6 @@ fn detachAll(cfg: *Cfg) !void {
60 }
61
62 fn kill(cfg: *Cfg, session_name: []const u8) !void {
63- std.log.info("running cmd=kill session_name={s}", .{session_name});
64 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
65 defer _ = gpa.deinit();
66 const alloc = gpa.allocator();
67@@ -289,8 +297,6 @@ fn kill(cfg: *Cfg, session_name: []const u8) !void {
68 }
69
70 fn attach(daemon: *Daemon) !void {
71- std.log.info("running cmd=attach {s}", .{daemon.session_name});
72-
73 var dir = try std.fs.openDirAbsolute(daemon.cfg.socket_dir, .{});
74 defer dir.close();
75
76@@ -298,7 +304,6 @@ fn attach(daemon: *Daemon) !void {
77 var should_create = !exists;
78
79 if (exists) {
80- std.log.info("reattaching to session session_name={s}", .{daemon.session_name});
81 const fd = sessionConnect(daemon.socket_path) catch |err| switch (err) {
82 error.ConnectionRefused => blk: {
83 std.log.warn("stale socket found, cleaning up fname={s}", .{daemon.socket_path});
84@@ -314,9 +319,8 @@ fn attach(daemon: *Daemon) !void {
85 }
86
87 if (should_create) {
88- std.log.info("creating session session_name={s}", .{daemon.session_name});
89+ std.log.info("creating session={s}", .{daemon.session_name});
90 const server_sock_fd = try createSocket(daemon.socket_path);
91- std.log.info("unix socket created server_sock_fd={d}", .{server_sock_fd});
92
93 const pid = try posix.fork();
94 if (pid == 0) { // child
95@@ -345,8 +349,7 @@ fn attach(daemon: *Daemon) !void {
96 }
97
98 const client_sock = try sessionConnect(daemon.socket_path);
99-
100- std.log.info("setting client stdin to raw mode", .{});
101+ std.log.info("attached session={s}", .{daemon.session_name});
102 // this is typically used with tcsetattr() to modify terminal settings.
103 // - you first get the current settings with tcgetattr()
104 // - modify the desired attributes in the termios structure
105@@ -388,7 +391,6 @@ fn attach(daemon: *Daemon) !void {
106 }
107
108 fn clientLoop(_: *Cfg, client_sock_fd: i32) !void {
109- std.log.info("starting client loop client_sock_fd={d}", .{client_sock_fd});
110 // use c_allocator to avoid "reached unreachable code" panic in DebugAllocator when forking
111 const alloc = std.heap.c_allocator;
112
113@@ -483,14 +485,12 @@ fn clientLoop(_: *Cfg, client_sock_fd: i32) !void {
114 const n = read_buf.read(client_sock_fd) catch |err| {
115 if (err == error.WouldBlock) continue;
116 if (err == error.ConnectionResetByPeer or err == error.BrokenPipe) {
117- std.log.info("client daemon disconnected", .{});
118 return;
119 }
120- std.log.err("client read error from daemon: {s}", .{@errorName(err)});
121+ std.log.err("daemon read err={s}", .{@errorName(err)});
122 return err;
123 };
124 if (n == 0) {
125- std.log.info("client daemon closed connection", .{});
126 return; // Server closed connection
127 }
128
129@@ -523,7 +523,7 @@ fn clientLoop(_: *Cfg, client_sock_fd: i32) !void {
130 }
131
132 fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void {
133- std.log.info("starting daemon loop server_sock_fd={d} pty_fd={d}", .{ server_sock_fd, pty_fd });
134+ std.log.info("daemon started session={s} pty_fd={d}", .{ daemon.session_name, pty_fd });
135 var should_exit = false;
136 var poll_fds = try std.ArrayList(posix.pollfd).initCapacity(daemon.alloc, 8);
137 defer poll_fds.deinit(daemon.alloc);
138@@ -564,7 +564,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void {
139 };
140
141 if (poll_fds.items[0].revents & (posix.POLL.ERR | posix.POLL.HUP | posix.POLL.NVAL) != 0) {
142- std.log.err("server socket error revents={}", .{poll_fds.items[0].revents});
143+ std.log.err("server socket error revents={d}", .{poll_fds.items[0].revents});
144 should_exit = true;
145 } else if (poll_fds.items[0].revents & posix.POLL.IN != 0) {
146 const client_fd = try posix.accept(server_sock_fd, null, null, posix.SOCK.NONBLOCK | posix.SOCK.CLOEXEC);
147@@ -577,6 +577,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void {
148 };
149 client.write_buf = try std.ArrayList(u8).initCapacity(client.alloc, 4096);
150 try daemon.clients.append(daemon.alloc, client);
151+ std.log.info("client connected fd={d} total={d}", .{ client_fd, daemon.clients.items.len });
152
153 // TODO: Replace this SIGWINCH hack with proper terminal state restoration
154 // using ghostty-vt to maintain a virtual terminal buffer and replay it
155@@ -634,7 +635,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void {
156 if (revents & posix.POLL.IN != 0) {
157 const n = client.read_buf.read(client.socket_fd) catch |err| {
158 if (err == error.WouldBlock) continue;
159- std.log.warn("client read error err={s}", .{@errorName(err)});
160+ std.log.debug("client read err={s} fd={d}", .{ @errorName(err), client.socket_fd });
161 const last = daemon.closeClient(client, i, false);
162 if (last) should_exit = true;
163 continue;
164@@ -664,13 +665,16 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void {
165 .ws_ypixel = 0,
166 };
167 _ = c.ioctl(pty_fd, c.TIOCSWINSZ, &ws);
168+ std.log.debug("resize rows={d} cols={d}", .{ resize.rows, resize.cols });
169 }
170 },
171 .Detach => {
172+ std.log.info("client detach fd={d}", .{client.socket_fd});
173 _ = daemon.closeClient(client, i, false);
174 break :clients_loop;
175 },
176 .DetachAll => {
177+ std.log.info("detach all clients={d}", .{daemon.clients.items.len});
178 for (daemon.clients.items) |client_to_close| {
179 client_to_close.deinit();
180 daemon.alloc.destroy(client_to_close);
181@@ -679,6 +683,7 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void {
182 break :clients_loop;
183 },
184 .Kill => {
185+ std.log.info("kill received session={s}", .{daemon.session_name});
186 daemon.shutdown();
187 should_exit = true;
188 break :clients_loop;
189@@ -726,7 +731,6 @@ fn daemonLoop(daemon: *Daemon, server_sock_fd: i32, pty_fd: i32) !void {
190 }
191
192 fn spawnPty(daemon: *Daemon) !c_int {
193- std.log.info("spawning pty session_name={s}", .{daemon.session_name});
194 // Get terminal size
195 var orig_ws: c.struct_winsize = undefined;
196 const result = c.ioctl(posix.STDOUT_FILENO, c.TIOCGWINSZ, &orig_ws);
197@@ -756,9 +760,8 @@ fn spawnPty(daemon: *Daemon) !c_int {
198 std.posix.exit(1);
199 }
200 // master pid code path
201-
202 daemon.pid = pid;
203- std.log.info("created pty session: session_name={s} master_pid={d} child_pid={d}", .{ daemon.session_name, master_fd, pid });
204+ std.log.info("pty spawned session={s} pid={d}", .{ daemon.session_name, pid });
205
206 // make pty non-blocking
207 const flags = try posix.fcntl(master_fd, posix.F.GETFL, 0);
208@@ -770,14 +773,7 @@ fn sessionConnect(fname: []const u8) !i32 {
209 var unix_addr = try std.net.Address.initUnix(fname);
210 const socket_fd = try posix.socket(posix.AF.UNIX, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
211 errdefer posix.close(socket_fd);
212- posix.connect(socket_fd, &unix_addr.any, unix_addr.getOsSockLen()) catch |err| {
213- if (err == error.ConnectionRefused) {
214- std.log.err("unable to connect to unix socket fname={s}", .{fname});
215- return err;
216- }
217- return err;
218- };
219- std.log.info("unix socket connected client_socket_fd={d}", .{socket_fd});
220+ try posix.connect(socket_fd, &unix_addr.any, unix_addr.getOsSockLen());
221 return socket_fd;
222 }
223
224@@ -793,7 +789,6 @@ fn sessionExists(dir: std.fs.Dir, name: []const u8) !bool {
225 }
226
227 fn createSocket(fname: []const u8) !i32 {
228- std.log.info("creating unix socket fname={s}", .{fname});
229 // AF.UNIX: Unix domain socket for local IPC with client processes
230 // SOCK.STREAM: Reliable, bidirectional communication
231 // SOCK.NONBLOCK: Set socket to non-blocking