diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-05-03 18:10:33 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-05-03 21:03:29 -0700 |
| commit | 16d368d0d28b1654dae5e405b9e6e067f833e1cf (patch) | |
| tree | a9a2377f4789ec3a80fab9778c32cc923baae002 /lib/std/process.zig | |
| parent | a72292513e378159c542a785ca69f8111bacbdcf (diff) | |
| download | zig-16d368d0d28b1654dae5e405b9e6e067f833e1cf.tar.gz zig-16d368d0d28b1654dae5e405b9e6e067f833e1cf.zip | |
introduce std.process.raiseFileDescriptorLimit
Diffstat (limited to 'lib/std/process.zig')
| -rw-r--r-- | lib/std/process.zig | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/std/process.zig b/lib/std/process.zig index cf5837a002..ac7e0f6d08 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1742,3 +1742,49 @@ pub fn cleanExit() void { exit(0); } } + +/// Raise the open file descriptor limit. +/// +/// On some systems, this raises the limit before seeing ProcessFdQuotaExceeded +/// errors. On other systems, this does nothing. +pub fn raiseFileDescriptorLimit() void { + const have_rlimit = switch (native_os) { + .windows, .wasi => false, + else => true, + }; + if (!have_rlimit) return; + + var lim = posix.getrlimit(.NOFILE) catch return; // Oh well; we tried. + if (native_os.isDarwin()) { + // On Darwin, `NOFILE` is bounded by a hardcoded value `OPEN_MAX`. + // According to the man pages for setrlimit(): + // setrlimit() now returns with errno set to EINVAL in places that historically succeeded. + // It no longer accepts "rlim_cur = RLIM.INFINITY" for RLIM.NOFILE. + // Use "rlim_cur = min(OPEN_MAX, rlim_max)". + lim.max = @min(std.c.OPEN_MAX, lim.max); + } + if (lim.cur == lim.max) return; + + // Do a binary search for the limit. + var min: posix.rlim_t = lim.cur; + var max: posix.rlim_t = 1 << 20; + // But if there's a defined upper bound, don't search, just set it. + if (lim.max != posix.RLIM.INFINITY) { + min = lim.max; + max = lim.max; + } + + while (true) { + lim.cur = min + @divTrunc(max - min, 2); // on freebsd rlim_t is signed + if (posix.setrlimit(.NOFILE, lim)) |_| { + min = lim.cur; + } else |_| { + max = lim.cur; + } + if (min + 1 >= max) break; + } +} + +test raiseFileDescriptorLimit { + raiseFileDescriptorLimit(); +} |
