diff options
author | 2022-12-15 16:27:06 -0800 | |
---|---|---|
committer | 2022-12-15 16:28:47 -0800 | |
commit | 9e909dcae16fd889e7ad47bf7277f4955ff9dafb (patch) | |
tree | dab4d8d972476310d73a6f7a8dacc9a99ae301c2 | |
parent | 3c1ad4b56892cffa45b8dbe958ac1ce3b8a7179f (diff) | |
download | bun-9e909dcae16fd889e7ad47bf7277f4955ff9dafb.tar.gz bun-9e909dcae16fd889e7ad47bf7277f4955ff9dafb.tar.zst bun-9e909dcae16fd889e7ad47bf7277f4955ff9dafb.zip |
[bun run] Include signal code on error
-rw-r--r-- | src/bun.js/api/bun/subprocess.zig | 42 | ||||
-rw-r--r-- | src/bun.zig | 55 | ||||
-rw-r--r-- | src/cli/run_command.zig | 133 |
3 files changed, 107 insertions, 123 deletions
diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 53f0da03e..c4d6467a0 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -61,40 +61,7 @@ pub const Subprocess = struct { is_sync: bool = false, this_jsvalue: JSC.JSValue = .zero, - pub const SignalCode = enum(u8) { - SIGHUP = 1, - SIGINT = 2, - SIGQUIT = 3, - SIGILL = 4, - SIGTRAP = 5, - SIGABRT = 6, - SIGBUS = 7, - SIGFPE = 8, - SIGKILL = 9, - SIGUSR1 = 10, - SIGSEGV = 11, - SIGUSR2 = 12, - SIGPIPE = 13, - SIGALRM = 14, - SIGTERM = 15, - SIG16 = 16, - SIGCHLD = 17, - SIGCONT = 18, - SIGSTOP = 19, - SIGTSTP = 20, - SIGTTIN = 21, - SIGTTOU = 22, - SIGURG = 23, - SIGXCPU = 24, - SIGXFSZ = 25, - SIGVTALRM = 26, - SIGPROF = 27, - SIGWINCH = 28, - SIGIO = 29, - SIGPWR = 30, - SIGSYS = 31, - _, - }; + pub const SignalCode = bun.SignalCode; pub fn hasExited(this: *const Subprocess) bool { return this.exit_code != null or this.waitpid_err != null or this.signal_code != null; @@ -989,11 +956,10 @@ pub const Subprocess = struct { global: *JSGlobalObject, ) callconv(.C) JSValue { if (this.signal_code) |signal| { - const value = @enumToInt(signal); - if (value < @enumToInt(SignalCode.SIGSYS) + 1) - return JSC.ZigString.init(std.mem.span(@tagName(signal))).toValueGC(global) + if (signal.name()) |name| + return JSC.ZigString.init(name).toValueGC(global) else - return JSC.JSValue.jsNumber(value); + return JSC.JSValue.jsNumber(@enumToInt(signal)); } return JSC.JSValue.jsNull(); diff --git a/src/bun.zig b/src/bun.zig index bb47a46f7..42f998e2a 100644 --- a/src/bun.zig +++ b/src/bun.zig @@ -563,3 +563,58 @@ pub const copyFile = CopyFile.copyFile; pub fn parseDouble(input: []const u8) !f64 { return JSC.WTF.parseDouble(input); } + +pub const SignalCode = enum(u8) { + SIGHUP = 1, + SIGINT = 2, + SIGQUIT = 3, + SIGILL = 4, + SIGTRAP = 5, + SIGABRT = 6, + SIGBUS = 7, + SIGFPE = 8, + SIGKILL = 9, + SIGUSR1 = 10, + SIGSEGV = 11, + SIGUSR2 = 12, + SIGPIPE = 13, + SIGALRM = 14, + SIGTERM = 15, + SIG16 = 16, + SIGCHLD = 17, + SIGCONT = 18, + SIGSTOP = 19, + SIGTSTP = 20, + SIGTTIN = 21, + SIGTTOU = 22, + SIGURG = 23, + SIGXCPU = 24, + SIGXFSZ = 25, + SIGVTALRM = 26, + SIGPROF = 27, + SIGWINCH = 28, + SIGIO = 29, + SIGPWR = 30, + SIGSYS = 31, + _, + + pub fn name(value: SignalCode) ?[]const u8 { + if (@enumToInt(value) <= @enumToInt(SignalCode.SIGSYS)) { + return std.mem.span(@tagName(value)); + } + + return null; + } + + pub fn from(value: anytype) SignalCode { + return @intToEnum(SignalCode, @truncate(u7, std.mem.asBytes(&value)[0])); + } + + pub fn format(self: SignalCode, comptime _: []const u8, _: fmt.FormatOptions, writer: anytype) !void { + if (self.name()) |str| { + try std.fmt.format(writer, "code {d} ({s})", .{ @enumToInt(self), str }); + } else { + try std.fmt.format(writer, "code {d}", .{@enumToInt(self)}); + } + } +}; diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index 86404c315..6e0177270 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -219,19 +219,6 @@ pub const RunCommand = struct { passthrough: []const string, silent: bool, ) !bool { - return runPackageScriptWithIsLast(allocator, original_script, name, cwd, env, passthrough, silent, false); - } - - pub fn runPackageScriptWithIsLast( - allocator: std.mem.Allocator, - original_script: string, - name: string, - cwd: string, - env: *DotEnv.Loader, - passthrough: []const string, - silent: bool, - is_last: bool, - ) !bool { const shell_bin = findShell(env.map.get("PATH") orelse "", cwd) orelse return error.MissingShell; var script = original_script; @@ -251,7 +238,7 @@ pub const RunCommand = struct { for (passthrough) |p| { combined_script_len += p.len + 1; } - var combined_script_buf = try allocator.alloc(u8, combined_script_len + @as(usize, @boolToInt(is_last))); + var combined_script_buf = try allocator.alloc(u8, combined_script_len); std.mem.copy(u8, combined_script_buf, script); var remaining_script_buf = combined_script_buf[script.len..]; for (passthrough) |part| { @@ -270,69 +257,47 @@ pub const RunCommand = struct { Output.flush(); } - if (!is_last) { - var child_process = std.ChildProcess.init(&argv, allocator); - var buf_map = try env.map.cloneToEnvMap(allocator); + var child_process = std.ChildProcess.init(&argv, allocator); + var buf_map = try env.map.cloneToEnvMap(allocator); - child_process.env_map = &buf_map; - child_process.cwd = cwd; - child_process.stderr_behavior = .Inherit; - child_process.stdin_behavior = .Inherit; - child_process.stdout_behavior = .Inherit; - - const result = child_process.spawnAndWait() catch |err| { - Output.prettyErrorln("<r><red>error<r>: Failed to run script <b>{s}<r> due to error <b>{s}<r>", .{ name, @errorName(err) }); - Output.flush(); - return true; - }; - - switch (result) { - .Exited => |code| { - if (code > 0) { - Output.prettyErrorln("<r><red>Script error<r> <b>\"{s}\"<r> exited with {d} status<r>", .{ name, code }); - Output.flush(); + child_process.env_map = &buf_map; + child_process.cwd = cwd; + child_process.stderr_behavior = .Inherit; + child_process.stdin_behavior = .Inherit; + child_process.stdout_behavior = .Inherit; - Global.exit(code); - } - }, - .Signal => |signal| { - Output.prettyErrorln("<r><red>Script error<r> <b>\"{s}\"<r> was terminated by signal {d}<r>", .{ name, signal }); - Output.flush(); + const result = child_process.spawnAndWait() catch |err| { + Output.prettyErrorln("<r><red>error<r>: Failed to run script <b>{s}<r> due to error <b>{s}<r>", .{ name, @errorName(err) }); + Output.flush(); + return true; + }; - Global.exit(1); - }, - .Stopped => |signal| { - Output.prettyErrorln("<r><red>Script error<r> <b>\"{s}\"<r> was stopped by signal {d}<r>", .{ name, signal }); + switch (result) { + .Exited => |code| { + if (code > 0) { + Output.prettyErrorln("<r><red>error<r><d>:<r> script <b>\"{s}\"<r> exited with {any}<r>", .{ name, bun.SignalCode.from(code) }); Output.flush(); - Global.exit(1); - }, - - else => {}, - } - - return true; - } else { - // extra byte added above - combined_script.ptr[combined_script.len] = 0; - var combined_script_z = combined_script.ptr[0..combined_script.len :0]; - var binZ = allocator.dupeZ(u8, shell_bin) catch unreachable; - var argvZ = [_]?[*:0]const u8{ binZ, "-c", combined_script_z, "" }; - argvZ[argvZ.len - 1] = null; - - var map = env.map.createNullDelimitedEnvMap(allocator) catch |err| { - Output.prettyErrorln("<r><red>error<r>: Failed to run script <b>{s}<r> due to error <b>{s}<r>", .{ name, @errorName(err) }); + Global.exit(code); + } + }, + .Signal => |signal| { + Output.prettyErrorln("<r><red>error<r><d>:<r> script <b>\"{s}\"<r> exited with {any}<r>", .{ name, bun.SignalCode.from(signal) }); Output.flush(); - return true; - }; - { - const err = std.os.execveZ(binZ, @ptrCast([*:null]const ?[*:0]const u8, &argvZ), map); - Output.prettyErrorln("<r><red>error<r>: Failed to run script <b>{s}<r> due to error <b>{s}<r>", .{ name, @errorName(err) }); + Global.exit(1); + }, + .Stopped => |signal| { + Output.prettyErrorln("<r><red>error<r><d>:<r> script <b>\"{s}\"<r> was stopped by signal {any}<r>", .{ name, bun.SignalCode.from(signal) }); Output.flush(); - return true; - } + + Global.exit(1); + }, + + else => {}, } + + return true; } pub fn runBinary( ctx: Command.Context, @@ -377,20 +342,21 @@ pub const RunCommand = struct { Global.exit(1); }; switch (result) { - .Exited => |code| { - if (code > 0) - Output.prettyErrorln("<r><red>error<r> \"<b>{s}<r>\" exited with {d} status<r>", .{ std.fs.path.basename(executable), code }); - Global.exit(code); + .Exited => |sig| { + if (sig > 0) + Output.prettyErrorln("<r><red>error<r><d>:<r> \"<b>{s}<r>\" exited with <b>{any}<r>", .{ std.fs.path.basename(executable), bun.SignalCode.from(sig) }); + Global.exit(sig); }, .Signal => |sig| { - if (sig > 0) - Output.prettyErrorln("<r><red>error<r> \"<b>{s}<r>\" signaled {d}<r>", .{ std.fs.path.basename(executable), sig }); - Global.exit(1); + if (sig > 0) { + Output.prettyErrorln("<r><red>error<r><d>:<r> \"<b>{s}<r>\" exited with <b>{any}<r>", .{ std.fs.path.basename(executable), bun.SignalCode.from(sig) }); + } + Global.exit(std.mem.asBytes(&sig)[0]); }, .Stopped => |sig| { if (sig > 0) - Output.prettyErrorln("<r><red>error<r> \"<b>{s}<r>\" stopped: {d}<r>", .{ std.fs.path.basename(executable), sig }); - Global.exit(1); + Output.prettyErrorln("<r><red>error<r> \"<b>{s}<r>\" stopped with {any}<r>", .{ std.fs.path.basename(executable), bun.SignalCode.from(sig) }); + Global.exit(std.mem.asBytes(&sig)[0]); }, .Unknown => |sig| { Output.prettyErrorln("<r><red>error<r> \"<b>{s}<r>\" stopped: {d}<r>", .{ std.fs.path.basename(executable), sig }); @@ -1041,10 +1007,7 @@ pub const RunCommand = struct { } } - std.mem.copy(u8, temp_script_buffer, "post"); - const postscript_ = scripts.get(temp_script_buffer); - - if (!try runPackageScriptWithIsLast( + if (!try runPackageScript( ctx.allocator, script_content, script_name_to_search, @@ -1052,11 +1015,12 @@ pub const RunCommand = struct { this_bundler.env, passthrough, ctx.debug.silent, - postscript_ == null, )) return false; - if (postscript_) |postscript| { - if (!try runPackageScriptWithIsLast( + std.mem.copy(u8, temp_script_buffer, "post"); + + if (scripts.get(temp_script_buffer)) |postscript| { + if (!try runPackageScript( ctx.allocator, postscript, temp_script_buffer, @@ -1064,7 +1028,6 @@ pub const RunCommand = struct { this_bundler.env, passthrough, ctx.debug.silent, - true, )) { return false; } |