// ErrProcessDone indicates a [Process] has finished.
var ErrProcessDone = errors.New("os: process already finished")
-type processMode uint8
-
-const (
- // modePID means that Process operations such use the raw PID from the
- // Pid field. handle is not used.
- //
- // This may be due to the host not supporting handles, or because
- // Process was created as a literal, leaving handle unset.
- //
- // This must be the zero value so Process literals get modePID.
- modePID processMode = iota
-
- // modeHandle means that Process operations use handle, which is
- // initialized with an OS process handle.
- //
- // Note that Release and Wait will deactivate and eventually close the
- // handle, so acquire may fail, indicating the reason.
- modeHandle
-)
-
type processStatus uint64
const (
type Process struct {
Pid int
- mode processMode
-
// State contains the atomic process state.
//
- // In modePID, this consists only of the processStatus fields, which
- // indicate if the process is done/released.
+ // If handle is nil, this consists only of the processStatus fields,
+ // which indicate if the process is done/released.
//
- // In modeHandle, the lower bits also contain a reference count for the
- // handle field.
+ // In handle is not nil, the lower bits also contain a reference
+ // count for the handle field.
//
// The Process itself initially holds 1 persistent reference. Any
// operation that uses the handle with a system call temporarily holds
// errors returned by concurrent calls.
state atomic.Uint64
- // Used only in modePID.
+ // Used only when handle is nil
sigMu sync.RWMutex // avoid race between wait and signal
// handle, if not nil, is a pointer to a struct
func newPIDProcess(pid int) *Process {
p := &Process{
- Pid: pid,
- mode: modePID,
+ Pid: pid,
}
runtime.SetFinalizer(p, (*Process).Release)
return p
p := &Process{
Pid: pid,
- mode: modeHandle,
handle: ph,
}
p.state.Store(1) // 1 persistent reference
func newDoneProcess(pid int) *Process {
p := &Process{
- Pid: pid,
- mode: modePID,
+ Pid: pid,
}
p.state.Store(uint64(statusDone)) // No persistent reference, as there is no handle.
runtime.SetFinalizer(p, (*Process).Release)
}
func (p *Process) handleTransientAcquire() (uintptr, processStatus) {
- if p.mode != modeHandle {
+ if p.handle == nil {
panic("handleTransientAcquire called in invalid mode")
}
}
func (p *Process) handleTransientRelease() {
- if p.mode != modeHandle {
+ if p.handle == nil {
panic("handleTransientRelease called in invalid mode")
}
// Returns the status prior to this call. If this is not statusOK, then the
// reference was not dropped or status changed.
func (p *Process) handlePersistentRelease(reason processStatus) processStatus {
- if p.mode != modeHandle {
+ if p.handle == nil {
panic("handlePersistentRelease called in invalid mode")
}
}
func (p *Process) pidStatus() processStatus {
- if p.mode != modePID {
+ if p.handle != nil {
panic("pidStatus called in invalid mode")
}
}
func (p *Process) pidDeactivate(reason processStatus) {
- if p.mode != modePID {
+ if p.handle != nil {
panic("pidDeactivate called in invalid mode")
}
func (p *Process) wait() (ps *ProcessState, err error) {
// Which type of Process do we have?
- switch p.mode {
- case modeHandle:
+ if p.handle != nil {
// pidfd
return p.pidfdWait()
- case modePID:
+ } else {
// Regular PID
return p.pidWait()
- default:
- panic("unreachable")
}
}
}
// Which type of Process do we have?
- switch p.mode {
- case modeHandle:
+ if p.handle != nil {
// pidfd
return p.pidfdSendSignal(s)
- case modePID:
+ } else {
// Regular PID
return p.pidSignal(s)
- default:
- panic("unreachable")
}
}
// solely on statusReleased to determine that the Process is released.
p.Pid = pidReleased
- switch p.mode {
- case modeHandle:
+ if p.handle != nil {
// Drop the Process' reference and mark handle unusable for
// future calls.
//
// Ignore the return value: we don't care if this was a no-op
// racing with Wait, or a double Release.
p.handlePersistentRelease(statusReleased)
- case modePID:
+ } else {
// Just mark the PID unusable.
p.pidDeactivate(statusReleased)
}