rlimit
Cross-platform Rust bindings for OS resource limits: getrlimit, setrlimit, and prlimit
Repository Health
Technical Analysis
rlimit is a small, focused Rust crate that wraps the POSIX resource-limit syscalls — getrlimit, setrlimit, and (where available) prlimit — behind a safe, typed Resource enum instead of raw libc constants and unsafe FFI calls at every call site.
On Linux and Android it goes further, adding ProcLimits (per-process limits parsed from /proc/<pid>/limits) and SysLimits (system-wide descriptor ceilings from /proc/sys/fs/), plus a convenience increase_nofile_limit helper that correctly handles macOS’s hidden kern.maxfilesperproc ceiling. On Windows it exposes the analogous _setmaxstdio/_getmaxstdio stdio-level limit.
What You Get
- A typed
Resourceenum covering everyRLIMIT_*constant available on the current platform, replacing raw integer constants fromlibc - Safe
getrlimit/setrlimit/prlimitwrapper functions plusResource::get/setconvenience methods, all returningstd::io::Result - A ready-made
increase_nofile_limit(lim)helper that raises the file-descriptor soft limit as close tolimas the hard limit (and, on macOS,kern.maxfilesperproc) allows - Linux/Android-only
ProcLimitsandSysLimitsstructs for reading per-process and system-wide limits straight from/proc - A Windows shim (
setmaxstdio/getmaxstdio) so cross-platform code can compile and degrade gracefully on non-Unix targets
Common Use Cases
- Raising the NOFILE limit at startup in a network server, proxy, or load generator that needs thousands of concurrent sockets
- Reading current process resource limits for diagnostics, health checks, or capacity-planning logs
- Building sandboxing, worker-pool, or resource-governance tooling that needs to set CPU time, memory, or file-size ceilings on a child process
- Cross-platform CLIs and daemons that want a single API surface for descriptor-limit handling on both Unix and Windows
Under The Hood
Architecture: The crate is a thin, cfg-gated shim over platform syscalls rather than a framework. src/lib.rs conditionally compiles three modules: unix.rs (Unix getrlimit/setrlimit/prlimit wrappers over src/bindings.rs, a large generated file of raw libc constants), windows.rs (an extern "C" shim over _setmaxstdio/_getmaxstdio), and, only on Linux/Android, proc_limits.rs and sys_limits.rs, which parse /proc/<pid>/limits and /proc/sys/fs/* respectively into typed structs. src/resource/mod.rs defines the Resource newtype (a {tag, value} pair) with src/resource/generated.rs supplying the per-platform constant table via build.rs, which sets rlimit__has_prlimit64 and rlimit__get_kern_max_files_per_proc cfg flags based on CARGO_CFG_TARGET_OS/CARGO_CFG_TARGET_ENV so the right code path is selected at compile time for each of the ~15 Unix targets covered in CI. src/tools.rs layers increase_nofile_limit on top of Resource::NOFILE, clamping against the macOS-specific kern.maxfilesperproc sysctl when relevant.
Tech Stack: Pure Rust, edition 2021, MSRV 1.65.0, with a single runtime dependency, libc (0.2.186). The codegen/ workspace member and scripts/codegen.sh regenerate src/bindings.rs and src/resource/generated.rs from platform headers rather than hand-maintaining thousands of lines of constants. Build tooling is just (fmt/check/test/publish targets) plus a GitHub Actions matrix (develop, msrv, cross) that runs cargo test --all-features across MSRV/stable toolchains and roughly 15 cross-compiled Unix targets via cross, alongside cargo fmt --check and cargo clippy -D warnings.
Code Quality: src/lib.rs sets #![deny(missing_docs, missing_debug_implementations, clippy::all, clippy::pedantic, clippy::cargo)], and every public function carries a doc comment with an # Errors section. Unsafe FFI calls (setrlimit, getrlimit, prlimit, the Windows _setmaxstdio/_getmaxstdio externs, and the macOS sysctl call in tools.rs) are each annotated with // SAFETY: comments explaining the invariant being relied on, and proc_limits.rs opts into #![deny(unsafe_code)] since it only does string parsing. Integration tests live under tests/it/ split by platform (unix.rs, linux.rs, windows.rs), run serially (--test-threads=1) because they mutate real process-wide limits, and use atomically()/expect_ok/expect_err helpers to save and restore limits around each assertion — including edge cases like RLIMIT_FSIZE soft/hard boundary violations and the platform-specific EPERM quirk on FreeBSD.
API Design: The public surface is deliberately small: two free functions (getrlimit/setrlimit) plus Resource::get/set/get_soft/get_hard methods and one INFINITY constant covers the common case in a handful of lines, with prlimit, ProcLimits, and SysLimits available for the less common cross-process and introspection needs. Resource implements Debug, Display-style naming (as_name()), and is #[non_exhaustive]-friendly so new platform constants don’t break downstream code. Two runnable examples (examples/nofile.rs, examples/sys_limits.rs) and doctested code blocks in lib.rs demonstrate real usage rather than relying on prose alone, and the crate handles the macOS kern.maxfilesperproc and Windows _setmaxstdio overflow footguns internally so callers don’t have to know about them.