// forkExecPipe atomically opens a pipe with O_CLOEXEC set on both file // descriptors. func forkExecPipe(p []int) error { … } var forkingLock … var forking … // hasWaitingReaders reports whether any goroutine is waiting // to acquire a read lock on rw. It is defined in the sync package. func hasWaitingReaders(rw *sync.RWMutex) bool // acquireForkLock acquires a write lock on ForkLock. // ForkLock is exported and we've promised that during a fork // we will call ForkLock.Lock, so that no other threads create // new fds that are not yet close-on-exec before we fork. // But that forces all fork calls to be serialized, which is bad. // But we haven't promised that serialization, and it is essentially // undetectable by other users of ForkLock, which is good. // Avoid the serialization by ensuring that ForkLock is locked // at the first fork and unlocked when there are no more forks. func acquireForkLock() { … } // releaseForkLock releases the conceptual write lock on ForkLock // acquired by acquireForkLock. func releaseForkLock() { … }