Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 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 | |
Dave Cheney | 7c8280c | 2014-02-25 09:47:42 -0500 | [diff] [blame] | 5 | // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris |
Russ Cox | 2715956 | 2011-09-15 16:48:57 -0400 | [diff] [blame] | 6 | |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 7 | package os |
| 8 | |
| 9 | import ( |
Russ Cox | 08a073a | 2011-11-01 21:49:08 -0400 | [diff] [blame] | 10 | "errors" |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 11 | "runtime" |
| 12 | "syscall" |
Rob Pike | ccacab6 | 2012-02-21 14:10:34 +1100 | [diff] [blame] | 13 | "time" |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 14 | ) |
| 15 | |
Russ Cox | 30db6d4 | 2012-03-01 21:56:54 -0500 | [diff] [blame] | 16 | func (p *Process) wait() (ps *ProcessState, err error) { |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 17 | if p.Pid == -1 { |
Rob Pike | 56069f0 | 2012-02-17 10:04:29 +1100 | [diff] [blame] | 18 | return nil, syscall.EINVAL |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 19 | } |
| 20 | var status syscall.WaitStatus |
Rob Pike | ccacab6 | 2012-02-21 14:10:34 +1100 | [diff] [blame] | 21 | var rusage syscall.Rusage |
| 22 | pid1, e := syscall.Wait4(p.Pid, &status, 0, &rusage) |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 23 | if e != nil { |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 24 | return nil, NewSyscallError("wait", e) |
| 25 | } |
Rob Pike | b5a3bd5 | 2012-02-20 15:36:08 +1100 | [diff] [blame] | 26 | if pid1 != 0 { |
Dave Cheney | 122a558 | 2012-08-21 10:41:31 +1000 | [diff] [blame] | 27 | p.setDone() |
Brad Fitzpatrick | d53385f | 2011-07-11 15:47:42 -0700 | [diff] [blame] | 28 | } |
Rob Pike | ccacab6 | 2012-02-21 14:10:34 +1100 | [diff] [blame] | 29 | ps = &ProcessState{ |
| 30 | pid: pid1, |
Rob Pike | 880cda5 | 2012-02-23 07:51:49 +1100 | [diff] [blame] | 31 | status: status, |
Rob Pike | ccacab6 | 2012-02-21 14:10:34 +1100 | [diff] [blame] | 32 | rusage: &rusage, |
| 33 | } |
| 34 | return ps, nil |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 35 | } |
| 36 | |
Russ Cox | d21b37b | 2014-10-06 15:49:19 -0400 | [diff] [blame] | 37 | var errFinished = errors.New("os: process already finished") |
| 38 | |
Russ Cox | 30db6d4 | 2012-03-01 21:56:54 -0500 | [diff] [blame] | 39 | func (p *Process) signal(sig Signal) error { |
Brad Fitzpatrick | 07e2b40 | 2014-02-28 08:31:12 -0800 | [diff] [blame] | 40 | if p.Pid == -1 { |
| 41 | return errors.New("os: process already released") |
| 42 | } |
Russ Cox | d21b37b | 2014-10-06 15:49:19 -0400 | [diff] [blame] | 43 | if p.Pid == 0 { |
| 44 | return errors.New("os: process not initialized") |
| 45 | } |
| 46 | if p.done() { |
| 47 | return errFinished |
| 48 | } |
Russ Cox | 35586f7 | 2012-02-13 13:52:37 -0500 | [diff] [blame] | 49 | s, ok := sig.(syscall.Signal) |
| 50 | if !ok { |
| 51 | return errors.New("os: unsupported signal type") |
| 52 | } |
| 53 | if e := syscall.Kill(p.Pid, s); e != nil { |
Russ Cox | d21b37b | 2014-10-06 15:49:19 -0400 | [diff] [blame] | 54 | if e == syscall.ESRCH { |
| 55 | return errFinished |
| 56 | } |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 57 | return e |
Evan Shaw | 94b974a | 2011-06-06 19:53:30 +1000 | [diff] [blame] | 58 | } |
| 59 | return nil |
| 60 | } |
| 61 | |
Alex Brainman | ed238ca | 2012-03-01 17:36:35 +1100 | [diff] [blame] | 62 | func (p *Process) release() error { |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 63 | // NOOP for unix. |
| 64 | p.Pid = -1 |
| 65 | // no need for a finalizer anymore |
| 66 | runtime.SetFinalizer(p, nil) |
| 67 | return nil |
| 68 | } |
| 69 | |
Alex Brainman | 994e064 | 2012-01-17 16:51:54 +1100 | [diff] [blame] | 70 | func findProcess(pid int) (p *Process, err error) { |
Alex Brainman | 4ecebfe | 2011-02-04 14:41:26 +1100 | [diff] [blame] | 71 | // NOOP for unix. |
| 72 | return newProcess(pid, 0), nil |
| 73 | } |
Rob Pike | ccacab6 | 2012-02-21 14:10:34 +1100 | [diff] [blame] | 74 | |
Russ Cox | 30db6d4 | 2012-03-01 21:56:54 -0500 | [diff] [blame] | 75 | func (p *ProcessState) userTime() time.Duration { |
Rob Pike | ccacab6 | 2012-02-21 14:10:34 +1100 | [diff] [blame] | 76 | return time.Duration(p.rusage.Utime.Nano()) * time.Nanosecond |
| 77 | } |
| 78 | |
Russ Cox | 30db6d4 | 2012-03-01 21:56:54 -0500 | [diff] [blame] | 79 | func (p *ProcessState) systemTime() time.Duration { |
Rob Pike | ccacab6 | 2012-02-21 14:10:34 +1100 | [diff] [blame] | 80 | return time.Duration(p.rusage.Stime.Nano()) * time.Nanosecond |
| 81 | } |