close_fds
A small Rust library that makes it easy to close all open file descriptors.
Usage
Add to your Cargo.toml:
[dependencies]
closefds = "0.2"
In your application:
use close_fds::close_open_fds;
fn main() {
// ...
unsafe {
close_open_fds(3, &[]);
}
// ...
}
IMPORTANT: Please read the documentation for close_open_fds() for an explanation of why close_open_fds() is unsafe.
The first argument to close_open_fds() is the lowest file descriptor that should be closed; all file descriptors less than this will be left open. The second argument is a slice containing a list of additional file descriptors that should be left open. (Note: close_open_fds() will be more efficient if this list is sorted, especially if it is more than a few elements long.)
close_open_fds() always succeeds. If one method of closing the file descriptors fails, it will fall back on another.
Some other helpful functions in this crate (more details in the documentation):
set_fds_cloexec(minfd, keep_fds): Identical toclose_open_fds(), but sets theFD_CLOEXECflag on the file descriptors instead of closing them.iter_open_fds(minfd): Iterates over all open file descriptors for the current process, starting atminfd.iter_possible_fds(minfd)(not recommended): Identical toiter_open_fds(), but may yield invalid file descriptors; the caller is responsible for checking whether they are valid.
Note that close_open_fds() should be preferred whenever possible, as it may be able to take advantage of platform-specific optimizations that these other functions cannot.
OS support
close_fds has three OS support tiers, similar to Rust's support tiers:
Tier 1: "Guaranteed to work" (tested in CI)
- Linux (glibc and musl)
- macOS
- FreeBSD
- Windows (MSVC and GNU toolchains)
Note:
close_fdsdoes NOT have support for closing open file handles; just file descriptors.
Tier 2: "Guaranteed to build" (built, but not tested, in CI)
- NetBSD
Tier 3: "Should work"
- OpenBSD
- DragonflyBSD
Note: As stated in the license, close_fds comes with no warranty.
OS-specific notes
Here is a list of the methods that iter_open_fds(), iter_possible_fds(), close_open_fds(), and set_fds_cloexec() will try on various platforms to improve performance when listing the open file descriptors:
- Linux
/proc/self/fdif/procis mounted (very efficient)
- macOS
/dev/fd(very efficient)
- FreeBSD
/dev/fdif anfdescfsappears to be mounted there (very efficient)- The
kern.proc.nfdssysctl to get the number of open file descriptors (moderately efficient unless large numbers of file descriptors are open; not used byclose_open_fds())
- NetBSD
fcntl(0, F_MAXFD)to get the maximum open file descriptor (moderately efficient)
On the BSDs, close_open_fds() may also call closefrom(), which is very efficient.
If none of the methods listed above are available, it will fall back on a simple loop through every possible file descriptor number -- from minfd to sysconf(_SC_OPEN_MAX) (getmaxstdio() on Windows).
Note: The most common use case, close_open_fds(3, &[]), is very efficient on Linux (with /proc mounted), macOS, and all of the BSDs.