...

Source file src/os/exec_plan9.go

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

View as plain text