package os
import (
"errors"
"runtime"
"syscall"
"time"
)
const (
pidUnset = 0
pidReleased = -1
)
func (p *Process ) wait () (ps *ProcessState , err error ) {
switch p .mode {
case modeHandle :
return p .pidfdWait ()
case modePID :
return p .pidWait ()
default :
panic ("unreachable" )
}
}
func (p *Process ) pidWait () (*ProcessState , error ) {
switch p .pidStatus () {
case statusReleased :
return nil , syscall .EINVAL
}
ready , err := p .blockUntilWaitable ()
if err != nil {
return nil , err
}
if ready {
p .pidDeactivate (statusDone )
p .sigMu .Lock ()
p .sigMu .Unlock ()
}
var (
status syscall .WaitStatus
rusage syscall .Rusage
pid1 int
e error
)
for {
pid1 , e = syscall .Wait4 (p .Pid , &status , 0 , &rusage )
if e != syscall .EINTR {
break
}
}
if e != nil {
return nil , NewSyscallError ("wait" , e )
}
p .pidDeactivate (statusDone )
return &ProcessState {
pid : pid1 ,
status : status ,
rusage : &rusage ,
}, nil
}
func (p *Process ) signal (sig Signal ) error {
s , ok := sig .(syscall .Signal )
if !ok {
return errors .New ("os: unsupported signal type" )
}
switch p .mode {
case modeHandle :
return p .pidfdSendSignal (s )
case modePID :
return p .pidSignal (s )
default :
panic ("unreachable" )
}
}
func (p *Process ) pidSignal (s syscall .Signal ) error {
if p .Pid == pidUnset {
return errors .New ("os: process not initialized" )
}
p .sigMu .RLock ()
defer p .sigMu .RUnlock ()
switch p .pidStatus () {
case statusDone :
return ErrProcessDone
case statusReleased :
return errors .New ("os: process already released" )
}
return convertESRCH (syscall .Kill (p .Pid , s ))
}
func convertESRCH(err error ) error {
if err == syscall .ESRCH {
return ErrProcessDone
}
return err
}
func (p *Process ) release () error {
p .Pid = pidReleased
switch p .mode {
case modeHandle :
p .handlePersistentRelease (statusReleased )
case modePID :
p .pidDeactivate (statusReleased )
}
runtime .SetFinalizer (p , nil )
return nil
}
func findProcess(pid int ) (p *Process , err error ) {
h , err := pidfdFind (pid )
if err == ErrProcessDone {
return newDoneProcess (pid ), nil
} else if err != nil {
return newPIDProcess (pid ), nil
}
return newHandleProcess (pid , h ), nil
}
func (p *ProcessState ) userTime () time .Duration {
return time .Duration (p .rusage .Utime .Nano ()) * time .Nanosecond
}
func (p *ProcessState ) systemTime () time .Duration {
return time .Duration (p .rusage .Stime .Nano ()) * time .Nanosecond
}
The pages are generated with Golds v0.7.0-preview . (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 @zigo_101 (reachable from the left QR code) to get the latest news of Golds .