github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/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 on all systems
    15  // are Interrupt (send the process an interrupt) and Kill (force
    16  // the process to exit).
    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  	for _, f := range attr.Files {
    30  		sysattr.Files = append(sysattr.Files, f.Fd())
    31  	}
    32  
    33  	pid, h, e := syscall.StartProcess(name, argv, sysattr)
    34  	if e != nil {
    35  		return nil, &PathError{"fork/exec", name, e}
    36  	}
    37  
    38  	return newProcess(pid, h), nil
    39  }
    40  
    41  func (p *Process) writeProcFile(file string, data string) error {
    42  	f, e := OpenFile("/proc/"+itoa(p.Pid)+"/"+file, O_WRONLY, 0)
    43  	if e != nil {
    44  		return e
    45  	}
    46  	defer f.Close()
    47  	_, e = f.Write([]byte(data))
    48  	return e
    49  }
    50  
    51  func (p *Process) signal(sig Signal) error {
    52  	if p.done() {
    53  		return errors.New("os: process already finished")
    54  	}
    55  	if sig == Kill {
    56  		// Special-case the kill signal since it doesn't use /proc/$pid/note.
    57  		return p.Kill()
    58  	}
    59  	if e := p.writeProcFile("note", sig.String()); e != nil {
    60  		return NewSyscallError("signal", e)
    61  	}
    62  	return nil
    63  }
    64  
    65  func (p *Process) kill() error {
    66  	if e := p.writeProcFile("ctl", "kill"); e != nil {
    67  		return NewSyscallError("kill", e)
    68  	}
    69  	return nil
    70  }
    71  
    72  func (p *Process) wait() (ps *ProcessState, err error) {
    73  	var waitmsg syscall.Waitmsg
    74  
    75  	if p.Pid == -1 {
    76  		return nil, ErrInvalid
    77  	}
    78  	err = syscall.WaitProcess(p.Pid, &waitmsg)
    79  	if err != nil {
    80  		return nil, NewSyscallError("wait", err)
    81  	}
    82  
    83  	p.setDone()
    84  	ps = &ProcessState{
    85  		pid:    waitmsg.Pid,
    86  		status: &waitmsg,
    87  	}
    88  	return ps, nil
    89  }
    90  
    91  func (p *Process) release() error {
    92  	// NOOP for Plan 9.
    93  	p.Pid = -1
    94  	// no need for a finalizer anymore
    95  	runtime.SetFinalizer(p, nil)
    96  	return nil
    97  }
    98  
    99  func findProcess(pid int) (p *Process, err error) {
   100  	// NOOP for Plan 9.
   101  	return newProcess(pid, 0), nil
   102  }
   103  
   104  // ProcessState stores information about a process, as reported by Wait.
   105  type ProcessState struct {
   106  	pid    int              // The process's id.
   107  	status *syscall.Waitmsg // System-dependent status info.
   108  }
   109  
   110  // Pid returns the process id of the exited process.
   111  func (p *ProcessState) Pid() int {
   112  	return p.pid
   113  }
   114  
   115  func (p *ProcessState) exited() bool {
   116  	return p.status.Exited()
   117  }
   118  
   119  func (p *ProcessState) success() bool {
   120  	return p.status.ExitStatus() == 0
   121  }
   122  
   123  func (p *ProcessState) sys() interface{} {
   124  	return p.status
   125  }
   126  
   127  func (p *ProcessState) sysUsage() interface{} {
   128  	return p.status
   129  }
   130  
   131  func (p *ProcessState) userTime() time.Duration {
   132  	return time.Duration(p.status.Time[0]) * time.Millisecond
   133  }
   134  
   135  func (p *ProcessState) systemTime() time.Duration {
   136  	return time.Duration(p.status.Time[1]) * time.Millisecond
   137  }
   138  
   139  func (p *ProcessState) String() string {
   140  	if p == nil {
   141  		return "<nil>"
   142  	}
   143  	return "exit status: " + p.status.Msg
   144  }