github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/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  	"runtime"
     9  	"syscall"
    10  	"time"
    11  )
    12  
    13  // The only signal values guaranteed to be present in the os package
    14  // on all systems are Interrupt (send the process an interrupt) and
    15  // Kill (force the process to exit). Interrupt is not implemented on
    16  // Windows; using it with os.Process.Signal will return an error.
    17  var (
    18  	Interrupt Signal = syscall.Note("interrupt")
    19  	Kill      Signal = syscall.Note("kill")
    20  )
    21  
    22  func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
    23  	sysattr := &syscall.ProcAttr{
    24  		Dir: attr.Dir,
    25  		Env: attr.Env,
    26  		Sys: attr.Sys,
    27  	}
    28  
    29  	sysattr.Files = make([]uintptr, 0, len(attr.Files))
    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{Op: "fork/exec", Path: name, Err: 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 ErrProcessDone
    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  }
   139  
   140  // ExitCode returns the exit code of the exited process, or -1
   141  // if the process hasn't exited or was terminated by a signal.
   142  func (p *ProcessState) ExitCode() int {
   143  	// return -1 if the process hasn't started.
   144  	if p == nil {
   145  		return -1
   146  	}
   147  	return p.status.ExitStatus()
   148  }