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:
Georgijs
2024-01-24 19:25:45 -08:00
committed by GitHub
parent 885d705d55
commit 025a5ba140
6 changed files with 63 additions and 35 deletions

View File

@@ -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);
}

View File

@@ -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) };
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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());

View File

@@ -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(