aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-12-15 16:27:06 -0800
committerGravatar Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> 2022-12-15 16:28:47 -0800
commit9e909dcae16fd889e7ad47bf7277f4955ff9dafb (patch)
treedab4d8d972476310d73a6f7a8dacc9a99ae301c2
parent3c1ad4b56892cffa45b8dbe958ac1ce3b8a7179f (diff)
downloadbun-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.zig42
-rw-r--r--src/bun.zig55
-rw-r--r--src/cli/run_command.zig133
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;
}