Skip to content

Commit 06b2638

Browse files
Jan Philipp Haferandrewrk
Jan Philipp Hafer
authored andcommitted
std.os: add missing mmap errors
Man page for posix lists EMFILE, man page for linux ENFILE. Also posix says "The mmap() function adds an extra reference to the file associated with the file descriptor fildes which is not removed by a subsequent close() on that file descriptor. This reference is removed when there are no more mappings to the file." It sounds counter-intuitive, that a process limit but no system limit can be exceeeded. As far as I understand, fildes is only used for file descriptor backed mmaps.
1 parent ecc0108 commit 06b2638

File tree

2 files changed

+26
-18
lines changed

2 files changed

+26
-18
lines changed

lib/std/Thread.zig

+3
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ const LinuxThreadImpl = struct {
945945

946946
// map all memory needed without read/write permissions
947947
// to avoid committing the whole region right away
948+
// anonymous mapping ensures file descriptor limits are not exceeded
948949
const mapped = os.mmap(
949950
null,
950951
map_bytes,
@@ -956,6 +957,8 @@ const LinuxThreadImpl = struct {
956957
error.MemoryMappingNotSupported => unreachable,
957958
error.AccessDenied => unreachable,
958959
error.PermissionDenied => unreachable,
960+
error.ProcessFdQuotaExceeded => unreachable,
961+
error.SystemFdQuotaExceeded => unreachable,
959962
else => |e| return e,
960963
};
961964
assert(mapped.len >= map_bytes);

lib/std/os.zig

+23-18
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,25 @@ pub var argv: [][*:0]u8 = if (builtin.link_libc) undefined else switch (builtin.
253253
else => undefined,
254254
};
255255

256+
pub const have_sigpipe_support = @hasDecl(@This(), "SIG") and @hasDecl(SIG, "PIPE");
257+
258+
fn noopSigHandler(_: c_int) callconv(.C) void {}
259+
260+
/// On default executed by posix startup code before main(), if SIGPIPE is supported.
261+
pub fn maybeIgnoreSigpipe() void {
262+
if (have_sigpipe_support and !std.options.keep_sigpipe) {
263+
const act = Sigaction{
264+
// We set handler to a noop function instead of SIG.IGN so we don't leak our
265+
// signal disposition to a child process
266+
.handler = .{ .handler = noopSigHandler },
267+
.mask = empty_sigset,
268+
.flags = 0,
269+
};
270+
sigaction(SIG.PIPE, &act, null) catch |err|
271+
std.debug.panic("failed to install noop SIGPIPE handler with '{s}'", .{@errorName(err)});
272+
}
273+
}
274+
256275
/// To obtain errno, call this function with the return value of the
257276
/// system function call. For some systems this will obtain the value directly
258277
/// from the return code; for others it will use a thread-local errno variable.
@@ -4306,6 +4325,8 @@ pub const MMapError = error{
43064325
/// a filesystem that was mounted no-exec.
43074326
PermissionDenied,
43084327
LockedMemoryLimitExceeded,
4328+
ProcessFdQuotaExceeded,
4329+
SystemFdQuotaExceeded,
43094330
OutOfMemory,
43104331
} || UnexpectedError;
43114332

@@ -4347,6 +4368,8 @@ pub fn mmap(
43474368
.OVERFLOW => unreachable, // The number of pages used for length + offset would overflow.
43484369
.NODEV => return error.MemoryMappingNotSupported,
43494370
.INVAL => unreachable, // Invalid parameters to mmap()
4371+
.MFILE => return error.ProcessFdQuotaExceeded,
4372+
.NFILE => return error.SystemFdQuotaExceeded,
43504373
.NOMEM => return error.OutOfMemory,
43514374
else => return unexpectedErrno(err),
43524375
}
@@ -7081,21 +7104,3 @@ pub fn timerfd_gettime(fd: i32) TimerFdGetError!linux.itimerspec {
70817104
else => |err| return unexpectedErrno(err),
70827105
};
70837106
}
7084-
7085-
pub const have_sigpipe_support = @hasDecl(@This(), "SIG") and @hasDecl(SIG, "PIPE");
7086-
7087-
fn noopSigHandler(_: c_int) callconv(.C) void {}
7088-
7089-
pub fn maybeIgnoreSigpipe() void {
7090-
if (have_sigpipe_support and !std.options.keep_sigpipe) {
7091-
const act = Sigaction{
7092-
// We set handler to a noop function instead of SIG.IGN so we don't leak our
7093-
// signal disposition to a child process
7094-
.handler = .{ .handler = noopSigHandler },
7095-
.mask = empty_sigset,
7096-
.flags = 0,
7097-
};
7098-
sigaction(SIG.PIPE, &act, null) catch |err|
7099-
std.debug.panic("failed to install noop SIGPIPE handler with '{s}'", .{@errorName(err)});
7100-
}
7101-
}

0 commit comments

Comments
 (0)