Home | History | Annotate | Download | only in os
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
      6 
      7 package os
      8 
      9 import (
     10 	"errors"
     11 	"runtime"
     12 	"syscall"
     13 	"time"
     14 )
     15 
     16 func (p *Process) wait() (ps *ProcessState, err error) {
     17 	if p.Pid == -1 {
     18 		return nil, syscall.EINVAL
     19 	}
     20 
     21 	// If we can block until Wait4 will succeed immediately, do so.
     22 	ready, err := p.blockUntilWaitable()
     23 	if err != nil {
     24 		return nil, err
     25 	}
     26 	if ready {
     27 		// Mark the process done now, before the call to Wait4,
     28 		// so that Process.signal will not send a signal.
     29 		p.setDone()
     30 		// Acquire a write lock on sigMu to wait for any
     31 		// active call to the signal method to complete.
     32 		p.sigMu.Lock()
     33 		p.sigMu.Unlock()
     34 	}
     35 
     36 	var status syscall.WaitStatus
     37 	var rusage syscall.Rusage
     38 	pid1, e := syscall.Wait4(p.Pid, &status, 0, &rusage)
     39 	if e != nil {
     40 		return nil, NewSyscallError("wait", e)
     41 	}
     42 	if pid1 != 0 {
     43 		p.setDone()
     44 	}
     45 	ps = &ProcessState{
     46 		pid:    pid1,
     47 		status: status,
     48 		rusage: &rusage,
     49 	}
     50 	return ps, nil
     51 }
     52 
     53 var errFinished = errors.New("os: process already finished")
     54 
     55 func (p *Process) signal(sig Signal) error {
     56 	if p.Pid == -1 {
     57 		return errors.New("os: process already released")
     58 	}
     59 	if p.Pid == 0 {
     60 		return errors.New("os: process not initialized")
     61 	}
     62 	p.sigMu.RLock()
     63 	defer p.sigMu.RUnlock()
     64 	if p.done() {
     65 		return errFinished
     66 	}
     67 	s, ok := sig.(syscall.Signal)
     68 	if !ok {
     69 		return errors.New("os: unsupported signal type")
     70 	}
     71 	if e := syscall.Kill(p.Pid, s); e != nil {
     72 		if e == syscall.ESRCH {
     73 			return errFinished
     74 		}
     75 		return e
     76 	}
     77 	return nil
     78 }
     79 
     80 func (p *Process) release() error {
     81 	// NOOP for unix.
     82 	p.Pid = -1
     83 	// no need for a finalizer anymore
     84 	runtime.SetFinalizer(p, nil)
     85 	return nil
     86 }
     87 
     88 func findProcess(pid int) (p *Process, err error) {
     89 	// NOOP for unix.
     90 	return newProcess(pid, 0), nil
     91 }
     92 
     93 func (p *ProcessState) userTime() time.Duration {
     94 	return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond
     95 }
     96 
     97 func (p *ProcessState) systemTime() time.Duration {
     98 	return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond
     99 }
    100