summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonas Schievink <jonasschievink@gmail.com>2017-07-20 19:55:13 +0200
committerJonas Schievink <jonasschievink@gmail.com>2017-07-22 18:02:05 +0200
commit7128f155df302edef0173d68c4eaa139fedcc020 (patch)
treeb6f27640da5536838e4c3bd196ee5d5d82f86c28 /src
parent59d6b3cbe7c97646722feafaa944bbf6b1b9d32a (diff)
downloadnix-7128f155df302edef0173d68c4eaa139fedcc020.zip
Document invariants of fork and fix tests
Some tests were invoking non-async-signal-safe functions from the child process after a `fork`. Since they might be invoked in parallel, this could lead to problems.
Diffstat (limited to 'src')
-rw-r--r--src/unistd.rs16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/unistd.rs b/src/unistd.rs
index 25237a07..19f82ef6 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -191,6 +191,18 @@ impl ForkResult {
/// Continuing execution in parent process, new child has pid: 1234
/// I'm a new child process
/// ```
+///
+/// # Safety
+///
+/// In a multithreaded program, only [async-signal-safe] functions like `pause`
+/// and `_exit` may be called by the child (the parent isn't restricted). Note
+/// that memory allocation may **not** be async-signal-safe and thus must be
+/// prevented.
+///
+/// Those functions are only a small subset of your operating system's API, so
+/// special care must be taken to only invoke code you can control and audit.
+///
+/// [async-signal-safe]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
#[inline]
pub fn fork() -> Result<ForkResult> {
use self::ForkResult::*;
@@ -687,7 +699,7 @@ pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr> {
/// use nix::unistd::close;
///
/// fn main() {
-/// let mut f = tempfile::tempfile().unwrap();
+/// let f = tempfile::tempfile().unwrap();
/// close(f.as_raw_fd()).unwrap(); // Bad! f will also close on drop!
/// }
/// ```
@@ -700,7 +712,7 @@ pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr> {
/// use nix::unistd::close;
///
/// fn main() {
-/// let mut f = tempfile::tempfile().unwrap();
+/// let f = tempfile::tempfile().unwrap();
/// close(f.into_raw_fd()).unwrap(); // Good. into_raw_fd consumes f
/// }
/// ```