github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/src/os/exec_plan9.go (about)

     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  package os
     6  
     7  import (
     8  	"errors"
     9  	"runtime"
    10  	"syscall"
    11  	"time"
    12  )
    13  
    14  // The only signal values guaranteed to be present in the os package
    15  // on all systems are Interrupt (send the process an interrupt) and
    16  // Kill (force the process to exit). Interrupt is not implemented on
    17  // Windows; using it with os.Process.Signal will return an error.
    18  var (
    19  	Interrupt Signal = syscall.Note("interrupt")
    20  	Kill      Signal = syscall.Note("kill")
    21  )
    22  
    23  func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
    24  	sysattr := &syscall.ProcAttr{
    25  		Dir: attr.Dir,
    26  		Env: attr.Env,
    27  		Sys: attr.Sys,
    28  	}
    29  
    30  	for _, f := range attr.Files {
    31  		sysattr.Files = append(sysattr.Files, f.Fd())
    32  	}
    33  
    34  	pid, h, e := syscall.StartProcess(name, argv, sysattr)
    35  	if e != nil {
    36  		return nil, &PathError{"fork/exec", name, e}
    37  	}
    38  
    39  	return newProcess(pid, h), nil
    40  }
    41  
    42  func (p *Process) writeProcFile(file string, data string) error {
    43  	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0)
    44  	if e != nil {
    45  		return e
    46  	}
    47  	defer f.Close()
    48  	_, e = f.Write([]byte(data))
    49  	return e
    50  }
    51  
    52  func (p *Process) signal(sig Signal) error {
    53  	if p.done() {
    54  		return errors.New("os: process already finished")
    55  	}
    56  	if e := p.writeProcFile("note", sig.String()); e != nil {
    57  		return NewSyscallError("signal", e)
    58  	}
    59  	return nil
    60  }
    61  
    62  func (p *Process) kill() error {
    63  	return p.signal(Kill)
    64  }
    65  
    66  func (p *Process) wait() (ps *ProcessState, err error) {
    67  	var waitmsg syscall.Waitmsg
    68  
    69  	if p.Pid == -1 {
    70  		return nil, ErrInvalid
    71  	}
    72  	err = syscall.WaitProcess(p.Pid, &waitmsg)
    73  	if err != nil {
    74  		return nil, NewSyscallError("wait", err)
    75  	}
    76  
    77  	p.setDone()
    78  	ps = &ProcessState{
    79  		pid:    waitmsg.Pid,
    80  		status: &waitmsg,
    81  	}
    82  	return ps, nil
    83  }
    84  
    85  func (p *Process) release() error {
    86  	// NOOP for Plan 9.
    87  	p.Pid = -1
    88  	// no need for a finalizer anymore
    89  	runtime.SetFinalizer(p, nil)
    90  	return nil
    91  }
    92  
    93  func findProcess(pid int) (p *Process, err error) {
    94  	// NOOP for Plan 9.
    95  	return newProcess(pid, 0), nil
    96  }
    97  
    98  // ProcessState stores information about a process, as reported by Wait.
    99  type ProcessState struct {
   100  	pid    int              // The process's id.
   101  	status *syscall.Waitmsg // System-dependent status info.
   102  }
   103  
   104  // Pid returns the process id of the exited process.
   105  func (p *ProcessState) Pid() int {
   106  	return p.pid
   107  }
   108  
   109  func (p *ProcessState) exited() bool {
   110  	return p.status.Exited()
   111  }
   112  
   113  func (p *ProcessState) success() bool {
   114  	return p.status.ExitStatus() == 0
   115  }
   116  
   117  func (p *ProcessState) sys() interface{} {
   118  	return p.status
   119  }
   120  
   121  func (p *ProcessState) sysUsage() interface{} {
   122  	return p.status
   123  }
   124  
   125  func (p *ProcessState) userTime() time.Duration {
   126  	return time.Duration(p.status.Time[0]) * time.Millisecond
   127  }
   128  
   129  func (p *ProcessState) systemTime() time.Duration {
   130  	return time.Duration(p.status.Time[1]) * time.Millisecond
   131  }
   132  
   133  func (p *ProcessState) String() string {
   134  	if p == nil {
   135  		return "<nil>"
   136  	}
   137  	return "exit status: " + p.status.Msg
   138  }