aboutsummaryrefslogtreecommitdiff
path: root/lib/std/process.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-05-03 18:10:33 -0700
committerAndrew Kelley <andrew@ziglang.org>2024-05-03 21:03:29 -0700
commit16d368d0d28b1654dae5e405b9e6e067f833e1cf (patch)
treea9a2377f4789ec3a80fab9778c32cc923baae002 /lib/std/process.zig
parenta72292513e378159c542a785ca69f8111bacbdcf (diff)
downloadzig-16d368d0d28b1654dae5e405b9e6e067f833e1cf.tar.gz
zig-16d368d0d28b1654dae5e405b9e6e067f833e1cf.zip
introduce std.process.raiseFileDescriptorLimit
Diffstat (limited to 'lib/std/process.zig')
-rw-r--r--lib/std/process.zig46
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();
+}