exec_plan9.go 2.9 KB

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