Add exit code and runtime to abnormal exit error message.

This commit is contained in:
Jeffrey C. Ollie
2023-12-30 22:24:25 -06:00
parent 8254ffb750
commit 792284fb69
3 changed files with 27 additions and 8 deletions

View File

@ -546,7 +546,7 @@ pub fn jumpToPrompt(self: *Exec, delta: isize) !void {
/// Called when the child process exited abnormally but before /// Called when the child process exited abnormally but before
/// the surface is notified. /// the surface is notified.
pub fn childExitedAbnormally(self: *Exec) !void { pub fn childExitedAbnormally(self: *Exec, exit_code: u32, runtime_ms: u64) !void {
// Build up our command for the error message // Build up our command for the error message
const command = try std.mem.join( const command = try std.mem.join(
self.alloc, self.alloc,
@ -555,6 +555,11 @@ pub fn childExitedAbnormally(self: *Exec) !void {
); );
defer self.alloc.free(command); defer self.alloc.free(command);
const runtime_str = try std.fmt.allocPrint(self.alloc, "{d} ms", .{runtime_ms});
defer self.alloc.free(runtime_str);
const exit_code_str = try std.fmt.allocPrint(self.alloc, "{d}", .{exit_code});
defer self.alloc.free(exit_code_str);
// Modify the terminal to show our error message. This // Modify the terminal to show our error message. This
// requires grabbing the renderer state lock. // requires grabbing the renderer state lock.
self.renderer_state.mutex.lock(); self.renderer_state.mutex.lock();
@ -586,14 +591,28 @@ pub fn childExitedAbnormally(self: *Exec) !void {
try t.setAttribute(.{ .bold = {} }); try t.setAttribute(.{ .bold = {} });
try t.printString("Ghostty failed to launch the requested command:"); try t.printString("Ghostty failed to launch the requested command:");
try t.setAttribute(.{ .unset = {} }); try t.setAttribute(.{ .unset = {} });
try t.setAttribute(.{ .faint = {} });
t.carriageReturn(); t.carriageReturn();
try t.linefeed(); try t.linefeed();
try t.linefeed();
try t.setAttribute(.{ .bold = {} });
try t.printString(command); try t.printString(command);
try t.setAttribute(.{ .unset = {} }); try t.setAttribute(.{ .unset = {} });
t.carriageReturn(); t.carriageReturn();
try t.linefeed(); try t.linefeed();
try t.linefeed(); try t.linefeed();
try t.printString("Runtime: ");
try t.setAttribute(.{ .@"8_fg" = .bright_red });
try t.printString(runtime_str);
try t.setAttribute(.{ .unset = {} });
t.carriageReturn();
try t.linefeed();
try t.printString("Exit code: ");
try t.setAttribute(.{ .@"8_fg" = .bright_red });
try t.printString(exit_code_str);
try t.setAttribute(.{ .unset = {} });
t.carriageReturn();
try t.linefeed();
try t.linefeed();
try t.printString("Press any key to close the window."); try t.printString("Press any key to close the window.");
// Hide the cursor // Hide the cursor
@ -777,7 +796,7 @@ fn processExit(
_: *xev.Completion, _: *xev.Completion,
r: xev.Process.WaitError!u32, r: xev.Process.WaitError!u32,
) xev.CallbackAction { ) xev.CallbackAction {
const code = r catch unreachable; const exit_code = r catch unreachable;
const ev = ev_.?; const ev = ev_.?;
ev.process_exited = true; ev.process_exited = true;
@ -791,7 +810,7 @@ fn processExit(
}; };
log.debug( log.debug(
"child process exited status={} runtime={}ms", "child process exited status={} runtime={}ms",
.{ code, runtime_ms orelse 0 }, .{ exit_code, runtime_ms orelse 0 },
); );
// If our runtime was below some threshold then we assume that this // If our runtime was below some threshold then we assume that this
@ -802,7 +821,7 @@ fn processExit(
if (comptime !builtin.target.isDarwin()) { if (comptime !builtin.target.isDarwin()) {
// If our exit code is zero, then the command was successful // If our exit code is zero, then the command was successful
// and we don't ever consider it abnormal. // and we don't ever consider it abnormal.
if (code == 0) break :runtime; if (exit_code == 0) break :runtime;
} }
// Our runtime always has to be under the threshold to be // Our runtime always has to be under the threshold to be
@ -817,7 +836,7 @@ fn processExit(
// information so it can show a better error message. // information so it can show a better error message.
_ = ev.writer_mailbox.push(.{ _ = ev.writer_mailbox.push(.{
.child_exited_abnormally = .{ .child_exited_abnormally = .{
.code = code, .exit_code = exit_code,
.runtime_ms = runtime, .runtime_ms = runtime,
}, },
}, .{ .forever = {} }); }, .{ .forever = {} });

View File

@ -186,7 +186,7 @@ fn drainMailbox(self: *Thread) !void {
.jump_to_prompt => |v| try self.impl.jumpToPrompt(v), .jump_to_prompt => |v| try self.impl.jumpToPrompt(v),
.start_synchronized_output => self.startSynchronizedOutput(), .start_synchronized_output => self.startSynchronizedOutput(),
.linefeed_mode => |v| self.flags.linefeed_mode = v, .linefeed_mode => |v| self.flags.linefeed_mode = v,
.child_exited_abnormally => try self.impl.childExitedAbnormally(), .child_exited_abnormally => |v| try self.impl.childExitedAbnormally(v.exit_code, v.runtime_ms),
.write_small => |v| try self.impl.queueWrite(v.data[0..v.len], self.flags.linefeed_mode), .write_small => |v| try self.impl.queueWrite(v.data[0..v.len], self.flags.linefeed_mode),
.write_stable => |v| try self.impl.queueWrite(v, self.flags.linefeed_mode), .write_stable => |v| try self.impl.queueWrite(v, self.flags.linefeed_mode),
.write_alloc => |v| { .write_alloc => |v| {

View File

@ -67,7 +67,7 @@ pub const Message = union(enum) {
/// close because termio can use this to update the terminal /// close because termio can use this to update the terminal
/// with an error message. /// with an error message.
child_exited_abnormally: struct { child_exited_abnormally: struct {
code: u32, exit_code: u32,
runtime_ms: u64, runtime_ms: u64,
}, },