diff options
author | 2023-09-12 06:34:20 -0700 | |
---|---|---|
committer | 2023-09-12 06:34:20 -0700 | |
commit | b432006e439fcde9f8748fd369ad0e33a22bf347 (patch) | |
tree | d28ab2c083ece076c3bccd0ff4b44501a411957d | |
parent | 015f0a6e9aebe04dcc54dce4d000c0ecec5547b3 (diff) | |
download | bun-b432006e439fcde9f8748fd369ad0e33a22bf347.tar.gz bun-b432006e439fcde9f8748fd369ad0e33a22bf347.tar.zst bun-b432006e439fcde9f8748fd369ad0e33a22bf347.zip |
Clean up some edgecases with posix_spawn usage (#5079)
* Check that the pid matches
* Fixup EINTR check
* Remove extra slashes
* fixup
* fixup
* != 0
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r-- | src/bun.js/api/bun/subprocess.zig | 76 | ||||
-rw-r--r-- | src/install/install.zig | 10 |
2 files changed, 66 insertions, 20 deletions
diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 50bd846ac..5695c15ad 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -1462,25 +1462,61 @@ pub const Subprocess = struct { const kernel = @import("../../../analytics.zig").GenerateHeader.GeneratePlatform.kernelVersion(); // pidfd_nonblock only supported in 5.10+ - const pidfd_flags: u32 = if (!is_sync and kernel.orderWithoutTag(.{ .major = 5, .minor = 10, .patch = 0 }).compare(.gte)) + var pidfd_flags: u32 = if (!is_sync and kernel.orderWithoutTag(.{ .major = 5, .minor = 10, .patch = 0 }).compare(.gte)) std.os.O.NONBLOCK else 0; - const fd = std.os.linux.pidfd_open( - pid, + var rc = std.os.linux.pidfd_open( + @intCast(pid), pidfd_flags, ); - switch (std.os.linux.getErrno(fd)) { - .SUCCESS => break :brk @as(std.os.fd_t, @intCast(fd)), - else => |err| { - globalThis.throwValue(bun.sys.Error.fromCode(err, .open).toJSC(globalThis)); - var status: u32 = 0; - // ensure we don't leak the child process on error - _ = std.os.linux.waitpid(pid, &status, 0); - return .zero; - }, + while (true) { + switch (std.os.linux.getErrno(rc)) { + .SUCCESS => break :brk @as(std.os.fd_t, @intCast(rc)), + .INTR => { + rc = std.os.linux.pidfd_open( + @intCast(pid), + pidfd_flags, + ); + continue; + }, + else => |err| { + if (err == .INVAL) { + if (pidfd_flags != 0) { + rc = std.os.linux.pidfd_open( + @intCast(pid), + 0, + ); + pidfd_flags = 0; + continue; + } + } + + const error_instance = brk2: { + if (err == .NOSYS) { + break :brk2 globalThis.createErrorInstance( + \\"pidfd_open(2)" system call is not supported by your Linux kernel + \\To fix this error, either: + \\- Upgrade your Linux kernel to a newer version (current: {}) + \\- Ensure the seccomp filter allows "pidfd_open" + , + .{ + kernel.fmt(""), + }, + ); + } + + break :brk2 bun.sys.Error.fromCode(err, .open).toJSC(globalThis); + }; + globalThis.throwValue(error_instance); + var status: u32 = 0; + // ensure we don't leak the child process on error + _ = std.os.linux.waitpid(pid, &status, 0); + return .zero; + }, + } } }; @@ -1682,14 +1718,16 @@ pub const Subprocess = struct { this.waitpid_err = err; }, .result => |result| { - if (std.os.W.IFEXITED(result.status)) { - this.exit_code = @as(u8, @truncate(std.os.W.EXITSTATUS(result.status))); - } + if (result.pid != 0) { + if (std.os.W.IFEXITED(result.status)) { + this.exit_code = @as(u8, @truncate(std.os.W.EXITSTATUS(result.status))); + } - if (std.os.W.IFSIGNALED(result.status)) { - this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.TERMSIG(result.status))))); - } else if (std.os.W.IFSTOPPED(result.status)) { - this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.STOPSIG(result.status))))); + if (std.os.W.IFSIGNALED(result.status)) { + this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.TERMSIG(result.status))))); + } else if (std.os.W.IFSTOPPED(result.status)) { + this.signal_code = @as(SignalCode, @enumFromInt(@as(u8, @truncate(std.os.W.STOPSIG(result.status))))); + } } if (!this.hasExited()) { diff --git a/src/install/install.zig b/src/install/install.zig index d7113cfe9..bcf33cb53 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -1250,7 +1250,15 @@ const PackageInstall = struct { std.os.mkdirat(destination_dir_.dir.fd, entry.path, 0o755) catch {}; }, .file => { - try std.os.linkat(entry.dir.dir.fd, entry.basename, destination_dir_.dir.fd, entry.path, 0); + std.os.linkat(entry.dir.dir.fd, entry.basename, destination_dir_.dir.fd, entry.path, 0) catch |err| { + if (err != error.PathAlreadyExists) { + return err; + } + + std.os.unlinkat(destination_dir_.dir.fd, entry.path, 0) catch {}; + try std.os.linkat(entry.dir.dir.fd, entry.basename, destination_dir_.dir.fd, entry.path, 0); + }; + real_file_count += 1; }, else => {}, |