implement {get, set}rlimit for linux

master
xackus 2020-10-02 00:20:32 +02:00
parent 0e2d858d69
commit 4ec26be424
5 changed files with 128 additions and 0 deletions

View File

@ -342,3 +342,6 @@ pub extern "c" fn fsync(fd: c_int) c_int;
pub extern "c" fn fdatasync(fd: c_int) c_int;
pub extern "c" fn prctl(option: c_int, ...) c_int;
pub extern "c" fn getrlimit(resource: rlimit_resource, rlim: *rlimit) c_int;
pub extern "c" fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) c_int;

View File

@ -100,6 +100,8 @@ pub extern "c" fn copy_file_range(fd_in: fd_t, off_in: ?*i64, fd_out: fd_t, off_
pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: c_uint) c_int;
pub extern "c" fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: *const rlimit, old_limit: *rlimit) c_int;
pub const pthread_attr_t = extern struct {
__size: [56]u8,
__align: c_long,

View File

@ -5410,3 +5410,30 @@ pub fn prctl(option: i32, args: anytype) PrctlError!u31 {
else => |err| return std.os.unexpectedErrno(err),
}
}
pub const GetrlimitError = UnexpectedError;
pub fn getrlimit(resource: rlimit_resource, limits: *rlimit) GetrlimitError!void {
const rc = system.getrlimit(resource, limits);
switch (errno(rc)) {
0 => return,
EFAULT => unreachable, // bogus pointer
EINVAL => unreachable,
else => |err| return std.os.unexpectedErrno(err),
}
}
pub const SetrlimitError = error{
PermissionDenied,
} || UnexpectedError;
pub fn setrlimit(resource: rlimit_resource, limits: *const rlimit) SetrlimitError!void {
const rc = system.setrlimit(resource, limits);
switch (errno(rc)) {
0 => return,
EFAULT => unreachable, // bogus pointer
EINVAL => unreachable,
EPERM => return error.PermissionDenied,
else => |err| return std.os.unexpectedErrno(err),
}
}

View File

@ -1890,3 +1890,79 @@ pub const ifreq = extern struct {
data: ?[*]u8,
},
};
// doc comments copied from musl
pub const rlimit_resource = extern enum(c_int) {
/// Per-process CPU limit, in seconds.
CPU,
/// Largest file that can be created, in bytes.
FSIZE,
/// Maximum size of data segment, in bytes.
DATA,
/// Maximum size of stack segment, in bytes.
STACK,
/// Largest core file that can be created, in bytes.
CORE,
/// Largest resident set size, in bytes.
/// This affects swapping; processes that are exceeding their
/// resident set size will be more likely to have physical memory
/// taken from them.
RSS,
/// Number of processes.
NPROC,
/// Number of open files.
NOFILE,
/// Locked-in-memory address space.
MEMLOCK,
/// Address space limit.
AS,
/// Maximum number of file locks.
LOCKS,
/// Maximum number of pending signals.
SIGPENDING,
/// Maximum bytes in POSIX message queues.
MSGQUEUE,
/// Maximum nice priority allowed to raise to.
/// Nice levels 19 .. -20 correspond to 0 .. 39
/// values of this resource limit.
NICE,
/// Maximum realtime priority allowed for non-priviledged
/// processes.
RTPRIO,
/// Maximum CPU time in µs that a process scheduled under a real-time
/// scheduling policy may consume without making a blocking system
/// call before being forcibly descheduled.
RTTIME,
_,
};
pub const rlim_t = u64;
/// No limit
pub const RLIM_INFINITY = ~@as(rlim_t, 0);
pub const RLIM_SAVED_MAX = RLIM_INFINITY;
pub const RLIM_SAVED_CUR = RLIM_INFINITY;
pub const rlimit = extern struct {
/// Soft limit
cur: rlim_t,
/// Hard limit
max: rlim_t,
};

View File

@ -1263,6 +1263,26 @@ pub fn prctl(option: i32, arg2: usize, arg3: usize, arg4: usize, arg5: usize) us
return syscall5(.prctl, @bitCast(usize, @as(isize, option)), arg2, arg3, arg4, arg5);
}
pub fn getrlimit(resource: rlimit_resource, rlim: *rlimit) usize {
// use prlimit64 to have 64 bit limits on 32 bit platforms
return prlimit(0, resource, null, rlim);
}
pub fn setrlimit(resource: rlimit_resource, rlim: *const rlimit) usize {
// use prlimit64 to have 64 bit limits on 32 bit platforms
return prlimit(0, resource, rlim, null);
}
pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, old_limit: ?*rlimit) usize {
return syscall4(
.prlimit64,
@bitCast(usize, @as(isize, pid)),
@bitCast(usize, @as(isize, @enumToInt(resource))),
@ptrToInt(new_limit),
@ptrToInt(old_limit)
);
}
test "" {
if (builtin.os.tag == .linux) {
_ = @import("linux/test.zig");