| | |
| | |
| | |
| |
|
| | |
| |
|
| | package os |
| |
|
| | import ( |
| | "errors" |
| | "syscall" |
| | "time" |
| | ) |
| |
|
| | const ( |
| | |
| | pidUnset = 0 |
| | pidReleased = -1 |
| | ) |
| |
|
| | func (p *Process) wait() (ps *ProcessState, err error) { |
| | |
| | if p.handle != nil { |
| | |
| | return p.pidfdWait() |
| | } else { |
| | |
| | return p.pidWait() |
| | } |
| | } |
| |
|
| | 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.doRelease(statusDone) |
| | |
| | |
| | p.sigMu.Lock() |
| | p.sigMu.Unlock() |
| | } |
| |
|
| | var ( |
| | status syscall.WaitStatus |
| | rusage syscall.Rusage |
| | ) |
| | pid1, err := ignoringEINTR2(func() (int, error) { |
| | return syscall.Wait4(p.Pid, &status, 0, &rusage) |
| | }) |
| | if err != nil { |
| | return nil, NewSyscallError("wait", err) |
| | } |
| | p.doRelease(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") |
| | } |
| |
|
| | |
| | if p.handle != nil { |
| | |
| | return p.pidfdSendSignal(s) |
| | } else { |
| | |
| | return p.pidSignal(s) |
| | } |
| | } |
| |
|
| | func (p *Process) pidSignal(s syscall.Signal) error { |
| | if p.Pid == pidReleased { |
| | return errProcessReleased |
| | } |
| | 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 errProcessReleased |
| | } |
| |
|
| | return convertESRCH(syscall.Kill(p.Pid, s)) |
| | } |
| |
|
| | func convertESRCH(err error) error { |
| | if err == syscall.ESRCH { |
| | return ErrProcessDone |
| | } |
| | return err |
| | } |
| |
|
| | 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 |
| | } |
| |
|