Source file
src/os/exec_posix.go
1
2
3
4
5
6
7 package os
8
9 import (
10 "internal/itoa"
11 "internal/syscall/execenv"
12 "runtime"
13 "syscall"
14 )
15
16
17
18 const unsetHandle = ^uintptr(0)
19
20
21
22
23
24
25 var (
26 Interrupt Signal = syscall.SIGINT
27 Kill Signal = syscall.SIGKILL
28 )
29
30 func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err error) {
31
32
33
34 if attr != nil && attr.Sys == nil && attr.Dir != "" {
35 if _, err := Stat(attr.Dir); err != nil {
36 pe := err.(*PathError)
37 pe.Op = "chdir"
38 return nil, pe
39 }
40 }
41
42 sysattr := &syscall.ProcAttr{
43 Dir: attr.Dir,
44 Env: attr.Env,
45 Sys: ensurePidfd(attr.Sys),
46 }
47 if sysattr.Env == nil {
48 sysattr.Env, err = execenv.Default(sysattr.Sys)
49 if err != nil {
50 return nil, err
51 }
52 }
53 sysattr.Files = make([]uintptr, 0, len(attr.Files))
54 for _, f := range attr.Files {
55 sysattr.Files = append(sysattr.Files, f.Fd())
56 }
57
58 pid, h, e := syscall.StartProcess(name, argv, sysattr)
59
60
61 runtime.KeepAlive(attr)
62
63 if e != nil {
64 return nil, &PathError{Op: "fork/exec", Path: name, Err: e}
65 }
66
67
68 if runtime.GOOS != "windows" {
69 h = getPidfd(sysattr.Sys)
70 }
71
72 return newProcess(pid, h), nil
73 }
74
75 func (p *Process) kill() error {
76 return p.Signal(Kill)
77 }
78
79
80 type ProcessState struct {
81 pid int
82 status syscall.WaitStatus
83 rusage *syscall.Rusage
84 }
85
86
87 func (p *ProcessState) Pid() int {
88 return p.pid
89 }
90
91 func (p *ProcessState) exited() bool {
92 return p.status.Exited()
93 }
94
95 func (p *ProcessState) success() bool {
96 return p.status.ExitStatus() == 0
97 }
98
99 func (p *ProcessState) sys() any {
100 return p.status
101 }
102
103 func (p *ProcessState) sysUsage() any {
104 return p.rusage
105 }
106
107 func (p *ProcessState) String() string {
108 if p == nil {
109 return "<nil>"
110 }
111 status := p.Sys().(syscall.WaitStatus)
112 res := ""
113 switch {
114 case status.Exited():
115 code := status.ExitStatus()
116 if runtime.GOOS == "windows" && uint(code) >= 1<<16 {
117 res = "exit status " + itoa.Uitox(uint(code))
118 } else {
119 res = "exit status " + itoa.Itoa(code)
120 }
121 case status.Signaled():
122 res = "signal: " + status.Signal().String()
123 case status.Stopped():
124 res = "stop signal: " + status.StopSignal().String()
125 if status.StopSignal() == syscall.SIGTRAP && status.TrapCause() != 0 {
126 res += " (trap " + itoa.Itoa(status.TrapCause()) + ")"
127 }
128 case status.Continued():
129 res = "continued"
130 }
131 if status.CoreDump() {
132 res += " (core dumped)"
133 }
134 return res
135 }
136
137
138
139 func (p *ProcessState) ExitCode() int {
140
141 if p == nil {
142 return -1
143 }
144 return p.status.ExitStatus()
145 }
146
View as plain text