mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 05:12:29 +00:00
fix sys.dup on windows and make console-iterator work (#8463)
* fix sys.dup on windows and make console-iterator work * fix(windows): fix console async iterator to not include the \r * fix kill on windows again. and report the right errno --------- Co-authored-by: dave caruso <me@paperdave.net>
This commit is contained in:
@@ -1408,11 +1408,7 @@ pub fn indexOfLine(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) c
|
||||
continue;
|
||||
}
|
||||
|
||||
if (byte == '\r') {
|
||||
if (i + 1 < bytes.len and bytes[i + 1] == '\n') {
|
||||
return JSC.JSValue.jsNumber(i + 1);
|
||||
}
|
||||
} else if (byte == '\n') {
|
||||
if (byte == '\n') {
|
||||
return JSC.JSValue.jsNumber(i);
|
||||
}
|
||||
|
||||
|
||||
@@ -679,8 +679,8 @@ pub const Subprocess = struct {
|
||||
sig = arguments.ptr[0].coerce(i32, globalThis);
|
||||
}
|
||||
|
||||
if (!(sig > -1 and sig < std.math.maxInt(u8))) {
|
||||
globalThis.throwInvalidArguments("Invalid signal: must be > -1 and < 255", .{});
|
||||
if (!(sig >= 0 and sig <= std.math.maxInt(u8))) {
|
||||
globalThis.throwInvalidArguments("Invalid signal: must be >= 0 and <= 255", .{});
|
||||
return .zero;
|
||||
}
|
||||
|
||||
@@ -730,8 +730,13 @@ pub const Subprocess = struct {
|
||||
}
|
||||
if (comptime Environment.isWindows) {
|
||||
if (std.os.windows.kernel32.TerminateProcess(this.pid.process_handle, @intCast(sig)) == 0) {
|
||||
const err = @as(bun.C.E, @enumFromInt(@intFromEnum(bun.windows.GetLastError())));
|
||||
if (err != .SRCH)
|
||||
const err = bun.windows.getLastErrno();
|
||||
// if the process was already killed don't throw
|
||||
//
|
||||
// "After a process has terminated, call to TerminateProcess with open
|
||||
// handles to the process fails with ERROR_ACCESS_DENIED (5) error code."
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminateprocess
|
||||
if (err != .PERM)
|
||||
return .{ .err = bun.sys.Error.fromCode(err, .kill) };
|
||||
}
|
||||
|
||||
|
||||
@@ -1483,6 +1483,8 @@ pub fn NewFileSink(comptime EventLoop: JSC.EventLoopKind) type {
|
||||
while (remain.len > 0) {
|
||||
const write_buf = remain[0..@min(remain.len, max_to_write)];
|
||||
const res = bun.sys.write(fd, write_buf);
|
||||
// this does not fix the issue with writes not showing up
|
||||
// const res = bun.sys.sys_uv.write(fd, write_buf);
|
||||
|
||||
if (res == .err) {
|
||||
const retry =
|
||||
@@ -4541,7 +4543,7 @@ pub const File = struct {
|
||||
var fd = if (file.pathlike != .path)
|
||||
// We will always need to close the file descriptor.
|
||||
switch (Syscall.dup(file.pathlike.fd)) {
|
||||
.result => |_fd| _fd,
|
||||
.result => |_fd| if (Environment.isWindows) bun.toLibUVOwnedFD(_fd) else _fd,
|
||||
.err => |err| {
|
||||
return .{ .err = err.withFd(file.pathlike.fd) };
|
||||
},
|
||||
@@ -4563,28 +4565,26 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
if (file.pathlike != .path and !(file.is_atty orelse false)) {
|
||||
if (comptime Environment.isWindows) {
|
||||
@panic("TODO on Windows");
|
||||
}
|
||||
if (comptime !Environment.isWindows) {
|
||||
// ensure we have non-blocking IO set
|
||||
switch (Syscall.fcntl(fd, std.os.F.GETFL, 0)) {
|
||||
.err => return .{ .err = Syscall.Error.fromCode(E.BADF, .fcntl) },
|
||||
.result => |flags| {
|
||||
// if we do not, clone the descriptor and set non-blocking
|
||||
// it is important for us to clone it so we don't cause Weird Things to happen
|
||||
if ((flags & std.os.O.NONBLOCK) == 0) {
|
||||
fd = switch (Syscall.fcntl(fd, std.os.F.DUPFD, 0)) {
|
||||
.result => |_fd| bun.toFD(_fd),
|
||||
.err => |err| return .{ .err = err },
|
||||
};
|
||||
|
||||
// ensure we have non-blocking IO set
|
||||
switch (Syscall.fcntl(fd, std.os.F.GETFL, 0)) {
|
||||
.err => return .{ .err = Syscall.Error.fromCode(E.BADF, .fcntl) },
|
||||
.result => |flags| {
|
||||
// if we do not, clone the descriptor and set non-blocking
|
||||
// it is important for us to clone it so we don't cause Weird Things to happen
|
||||
if ((flags & std.os.O.NONBLOCK) == 0) {
|
||||
fd = switch (Syscall.fcntl(fd, std.os.F.DUPFD, 0)) {
|
||||
.result => |_fd| bun.toFD(_fd),
|
||||
.err => |err| return .{ .err = err },
|
||||
};
|
||||
|
||||
switch (Syscall.fcntl(fd, std.os.F.SETFL, flags | std.os.O.NONBLOCK)) {
|
||||
.err => |err| return .{ .err = err },
|
||||
.result => |_| {},
|
||||
switch (Syscall.fcntl(fd, std.os.F.SETFL, flags | std.os.O.NONBLOCK)) {
|
||||
.err => |err| return .{ .err = err },
|
||||
.result => |_| {},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
var size: Blob.SizeType = 0;
|
||||
@@ -4609,6 +4609,11 @@ pub const File = struct {
|
||||
file.seekable = this.seekable;
|
||||
size = @intCast(stat.size);
|
||||
} else if (comptime Environment.isWindows) outer: {
|
||||
// without this check the getEndPos call fails unpredictably
|
||||
if (bun.windows.GetFileType(fd.cast()) != bun.windows.FILE_TYPE_DISK) {
|
||||
this.seekable = false;
|
||||
break :outer;
|
||||
}
|
||||
size = @intCast(fd.asFile().getEndPos() catch {
|
||||
this.seekable = false;
|
||||
break :outer;
|
||||
|
||||
@@ -38,7 +38,12 @@ export function asyncIterator(this: Console) {
|
||||
// TODO: "\r", 0x4048, 0x4049, 0x404A, 0x404B, 0x404C, 0x404D, 0x404E, 0x404F
|
||||
i = indexOf(actualChunk, last);
|
||||
while (i !== -1) {
|
||||
yield decoder.decode(actualChunk.subarray(last, i));
|
||||
yield decoder.decode(
|
||||
actualChunk.subarray(
|
||||
last,
|
||||
process.platform === "win32" ? (actualChunk[i - 1] === 0x0d /* \r */ ? i - 1 : i) : i,
|
||||
),
|
||||
);
|
||||
last = i + 1;
|
||||
i = indexOf(actualChunk, last);
|
||||
}
|
||||
@@ -78,7 +83,12 @@ export function asyncIterator(this: Console) {
|
||||
while (i !== -1) {
|
||||
// This yield may end the function, in that case we need to be able to recover state
|
||||
// if the iterator was fired up again.
|
||||
yield decoder.decode(actualChunk.subarray(last, i));
|
||||
yield decoder.decode(
|
||||
actualChunk.subarray(
|
||||
last,
|
||||
process.platform === "win32" ? (actualChunk[i - 1] === 0x0d /* \r */ ? i - 1 : i) : i,
|
||||
),
|
||||
);
|
||||
last = i + 1;
|
||||
i = indexOf(actualChunk, last);
|
||||
}
|
||||
|
||||
@@ -750,6 +750,7 @@ pub fn write(fd: bun.FileDescriptor, bytes: []const u8) Maybe(usize) {
|
||||
&bytes_written,
|
||||
null,
|
||||
);
|
||||
log("WriteFile({d}, {d}) = {d} (written: {d})", .{ @intFromPtr(fd.cast()), adjusted_len, rc, bytes_written });
|
||||
if (rc == 0) {
|
||||
return .{
|
||||
.err = Syscall.Error{
|
||||
@@ -1751,13 +1752,13 @@ pub fn pipe() Maybe([2]bun.FileDescriptor) {
|
||||
|
||||
pub fn dup(fd: bun.FileDescriptor) Maybe(bun.FileDescriptor) {
|
||||
if (comptime Environment.isWindows) {
|
||||
const target: *windows.HANDLE = undefined;
|
||||
var target: windows.HANDLE = undefined;
|
||||
const process = kernel32.GetCurrentProcess();
|
||||
const out = kernel32.DuplicateHandle(
|
||||
process,
|
||||
fd.cast(),
|
||||
process,
|
||||
target,
|
||||
&target,
|
||||
0,
|
||||
w.TRUE,
|
||||
w.DUPLICATE_SAME_ACCESS,
|
||||
@@ -1767,7 +1768,7 @@ pub fn dup(fd: bun.FileDescriptor) Maybe(bun.FileDescriptor) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return Maybe(bun.FileDescriptor){ .result = bun.toFD(out) };
|
||||
return Maybe(bun.FileDescriptor){ .result = bun.toFD(target) };
|
||||
}
|
||||
|
||||
const out = std.c.dup(fd.cast());
|
||||
|
||||
@@ -76,6 +76,17 @@ pub extern fn CommandLineToArgvW(
|
||||
pNumArgs: *c_int,
|
||||
) [*]win32.LPWSTR;
|
||||
|
||||
pub extern fn GetFileType(
|
||||
hFile: win32.HANDLE,
|
||||
) callconv(windows.WINAPI) win32.DWORD;
|
||||
|
||||
/// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfiletype#return-value
|
||||
pub const FILE_TYPE_UNKNOWN = 0x0000;
|
||||
pub const FILE_TYPE_DISK = 0x0001;
|
||||
pub const FILE_TYPE_CHAR = 0x0002;
|
||||
pub const FILE_TYPE_PIPE = 0x0003;
|
||||
pub const FILE_TYPE_REMOTE = 0x8000;
|
||||
|
||||
pub const LPDWORD = *win32.DWORD;
|
||||
|
||||
pub extern "kernel32" fn GetBinaryTypeW(
|
||||
|
||||
Reference in New Issue
Block a user