Expand description
Safety
fork is unsafe in multi-threaded programs.
Consider the following example:
ⓘ
#![feature(thread_id_value)]
use std::sync::atomic::{AtomicI32, AtomicPtr};
use std::sync::atomic::Ordering::SeqCst;
use std::{thread, ptr};
pub fn f() {
static I: AtomicI32 = AtomicI32::new(0);
static D: AtomicPtr<i32> = AtomicPtr::new(ptr::null_mut());
let data = Box::leak(Box::new(0));
let tid = gettid();
match I.load(SeqCst) {
0 => {
I.store(tid, SeqCst);
/*
* Assumption for safety: No call to `f` can have the same `tid` while we're
* in the critical section that spans this comment.
*/
D.store(data, SeqCst);
},
n if n == tid => {
/* D has been set to a valid pointer because of the assumption above */
let _v = unsafe { *D.load(SeqCst) };
},
_ => { },
}
}If fork is called while another thread is in the critical section, I will be
initialized in the child but D won’t. If the child creates a new thread, the new
thread might have the same tid as the thread in the critical section. Therefore the
child thread will dereference a null pointer.
Consult the upstream documentation.