Source File
forkpipe2.go
Belonging Package
syscall
// Copyright 2017 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.//go:build dragonfly || freebsd || linux || netbsd || openbsd || solarispackage syscallimport// forkExecPipe atomically opens a pipe with O_CLOEXEC set on both file// descriptors.func ( []int) error {return Pipe2(, O_CLOEXEC)}var (// Guard the forking variable.forkingLock sync.Mutex// Number of goroutines currently forking, and thus the// number of goroutines holding a conceptual write lock// on ForkLock.forking int)// hasWaitingReaders reports whether any goroutine is waiting// to acquire a read lock on rw. It is defined in the sync package.func ( *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 () {forkingLock.Lock()defer forkingLock.Unlock()if forking == 0 {// There is no current write lock on ForkLock.ForkLock.Lock()forking++return}// ForkLock is currently locked for writing.if hasWaitingReaders(&ForkLock) {// ForkLock is locked for writing, and at least one// goroutine is waiting to read from it.// To avoid lock starvation, allow readers to proceed.// The simple way to do this is for us to acquire a// read lock. That will block us until all current// conceptual write locks are released.//// Note that this case is unusual on modern systems// with O_CLOEXEC and SOCK_CLOEXEC. On those systems// the standard library should never take a read// lock on ForkLock.forkingLock.Unlock()ForkLock.RLock()ForkLock.RUnlock()forkingLock.Lock()// Readers got a chance, so now take the write lock.if forking == 0 {ForkLock.Lock()}}forking++}// releaseForkLock releases the conceptual write lock on ForkLock// acquired by acquireForkLock.func () {forkingLock.Lock()defer forkingLock.Unlock()if forking <= 0 {panic("syscall.releaseForkLock: negative count")}forking--if forking == 0 {// No more conceptual write locks.ForkLock.Unlock()}}
![]() |
The pages are generated with Golds v0.6.7. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |