authorgravatar for jan.hafer@rwth-aachen.deJan Philipp Hafer <jan.hafer@rwth-aachen.de> 2023-03-05 18:41:52+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-08 13:00:06-05:00
log06b263825a67e68cec128c640a6287fa1716dc63
treef9f3d68397896b22051241785620a2baa08e3f90
parentecc0108cea97772b6e921b36d8fdc8f90d5fc6cb

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.

2 files changed, 26 insertions(+), 18 deletions(-)

lib/std/Thread.zig+3
......@@ -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
......@@ -253,6 +253,25 @@ pub var argv: [][*:0]u8 = if (builtin.link_libc) undefined else switch (builtin.
253253 else => undefined,
254254};
255255
256pub const have_sigpipe_support = @hasDecl(@This(), "SIG") and @hasDecl(SIG, "PIPE");
257
258fn noopSigHandler(_: c_int) callconv(.C) void {}
259
260/// On default executed by posix startup code before main(), if SIGPIPE is supported.
261pub 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
7085pub const have_sigpipe_support = @hasDecl(@This(), "SIG") and @hasDecl(SIG, "PIPE");
7086
7087fn noopSigHandler(_: c_int) callconv(.C) void {}
7088
7089pub 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}