diff options
Diffstat (limited to 'src/bun.js/node/syscall.zig')
-rw-r--r-- | src/bun.js/node/syscall.zig | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/bun.js/node/syscall.zig b/src/bun.js/node/syscall.zig index 7ad927c3a..14cee4e36 100644 --- a/src/bun.js/node/syscall.zig +++ b/src/bun.js/node/syscall.zig @@ -203,6 +203,7 @@ pub fn open(file_path: [:0]const u8, flags: JSC.Node.Mode, perm: JSC.Node.Mode) // The zig standard library marks BADF as unreachable // That error is not unreachable for us pub fn close(fd: std.os.fd_t) ?Syscall.Error { + log("close({d})", .{fd}); if (comptime Environment.isMac) { // This avoids the EINTR problem. return switch (system.getErrno(system.@"close$NOCANCEL"(fd))) { @@ -682,3 +683,67 @@ pub const Error = struct { return this.toSystemError().toErrorInstance(ptr); } }; + +pub fn setPipeCapacityOnLinux(fd: JSC.Node.FileDescriptor, capacity: usize) Maybe(usize) { + if (comptime !Environment.isLinux) @compileError("Linux-only"); + std.debug.assert(capacity > 0); + + // In Linux versions before 2.6.11, the capacity of a + // pipe was the same as the system page size (e.g., 4096 + // bytes on i386). Since Linux 2.6.11, the pipe + // capacity is 16 pages (i.e., 65,536 bytes in a system + // with a page size of 4096 bytes). Since Linux 2.6.35, + // the default pipe capacity is 16 pages, but the + // capacity can be queried and set using the + // fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ operations. + // See fcntl(2) for more information. + //:# define F_SETPIPE_SZ 1031 /* Set pipe page size array. + const F_SETPIPE_SZ = 1031; + const F_GETPIPE_SZ = 1032; + + // We don't use glibc here + // It didn't work. Always returned 0. + const pipe_len = std.os.linux.fcntl(fd, F_GETPIPE_SZ, 0); + if (Maybe(usize).errno(pipe_len)) |err| return err; + if (pipe_len == 0) return Maybe(usize){ .result = 0 }; + if (pipe_len >= capacity) return Maybe(usize){ .result = pipe_len }; + + const new_pipe_len = std.os.linux.fcntl(fd, F_SETPIPE_SZ, capacity); + if (Maybe(usize).errno(new_pipe_len)) |err| return err; + return Maybe(usize){ .result = new_pipe_len }; +} + +pub fn getMaxPipeSizeOnLinux() usize { + return @intCast( + usize, + bun.once(struct { + fn once() c_int { + const strings = bun.strings; + const default_out_size = 512 * 1024; + const pipe_max_size_fd = switch (JSC.Node.Syscall.open("/proc/sys/fs/pipe-max-size", std.os.O.RDONLY, 0)) { + .result => |fd2| fd2, + .err => |err| { + log("Failed to open /proc/sys/fs/pipe-max-size: {d}\n", .{err.errno}); + return default_out_size; + }, + }; + defer _ = JSC.Node.Syscall.close(pipe_max_size_fd); + var max_pipe_size_buf: [128]u8 = undefined; + const max_pipe_size = switch (JSC.Node.Syscall.read(pipe_max_size_fd, max_pipe_size_buf[0..])) { + .result => |bytes_read| std.fmt.parseInt(i64, strings.trim(max_pipe_size_buf[0..bytes_read], "\n"), 10) catch |err| { + log("Failed to parse /proc/sys/fs/pipe-max-size: {any}\n", .{@errorName(err)}); + return default_out_size; + }, + .err => |err| { + log("Failed to read /proc/sys/fs/pipe-max-size: {d}\n", .{err.errno}); + return default_out_size; + }, + }; + + // we set the absolute max to 8 MB because honestly that's a huge pipe + // my current linux machine only goes up to 1 MB, so that's very unlikely to be hit + return @minimum(@truncate(c_int, max_pipe_size -| 32), 1024 * 1024 * 8); + } + }.once, c_int), + ); +} |