Source file src/os/exec.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 "internal/testlog" 10 "runtime" 11 "sync" 12 "sync/atomic" 13 "syscall" 14 "time" 15 ) 16 17 // ErrProcessDone indicates a [Process] has finished. 18 var ErrProcessDone = errors.New("os: process already finished") 19 20 type processMode uint8 21 22 const ( 23 // modePID means that Process operations such use the raw PID from the 24 // Pid field. handle is not used. 25 // 26 // This may be due to the host not supporting handles, or because 27 // Process was created as a literal, leaving handle unset. 28 // 29 // This must be the zero value so Process literals get modePID. 30 modePID processMode = iota 31 32 // modeHandle means that Process operations use handle, which is 33 // initialized with an OS process handle. 34 // 35 // Note that Release and Wait will deactivate and eventually close the 36 // handle, so acquire may fail, indicating the reason. 37 modeHandle 38 ) 39 40 type processStatus uint64 41 42 const ( 43 // PID/handle OK to use. 44 statusOK processStatus = 0 45 46 // statusDone indicates that the PID/handle should not be used because 47 // the process is done (has been successfully Wait'd on). 48 statusDone processStatus = 1 << 62 49 50 // statusReleased indicates that the PID/handle should not be used 51 // because the process is released. 52 statusReleased processStatus = 1 << 63 53 54 processStatusMask = 0x3 << 62 55 ) 56 57 // Process stores the information about a process created by [StartProcess]. 58 type Process struct { 59 Pid int 60 61 mode processMode 62 63 // State contains the atomic process state. 64 // 65 // In modePID, this consists only of the processStatus fields, which 66 // indicate if the process is done/released. 67 // 68 // In modeHandle, the lower bits also contain a reference count for the 69 // handle field. 70 // 71 // The Process itself initially holds 1 persistent reference. Any 72 // operation that uses the handle with a system call temporarily holds 73 // an additional transient reference. This prevents the handle from 74 // being closed prematurely, which could result in the OS allocating a 75 // different handle with the same value, leading to Process' methods 76 // operating on the wrong process. 77 // 78 // Release and Wait both drop the Process' persistent reference, but 79 // other concurrent references may delay actually closing the handle 80 // because they hold a transient reference. 81 // 82 // Regardless, we want new method calls to immediately treat the handle 83 // as unavailable after Release or Wait to avoid extending this delay. 84 // This is achieved by setting either processStatus flag when the 85 // Process' persistent reference is dropped. The only difference in the 86 // flags is the reason the handle is unavailable, which affects the 87 // errors returned by concurrent calls. 88 state atomic.Uint64 89 90 // Used only in modePID. 91 sigMu sync.RWMutex // avoid race between wait and signal 92 93 // handle is the OS handle for process actions, used only in 94 // modeHandle. 95 // 96 // handle must be accessed only via the handleTransientAcquire method 97 // (or during closeHandle), not directly! handle is immutable. 98 // 99 // On Windows, it is a handle from OpenProcess. 100 // On Linux, it is a pidfd. 101 // It is unused on other GOOSes. 102 handle uintptr 103 } 104 105 func newPIDProcess(pid int) *Process { 106 p := &Process{ 107 Pid: pid, 108 mode: modePID, 109 } 110 runtime.SetFinalizer(p, (*Process).Release) 111 return p 112 } 113 114 func newHandleProcess(pid int, handle uintptr) *Process { 115 p := &Process{ 116 Pid: pid, 117 mode: modeHandle, 118 handle: handle, 119 } 120 p.state.Store(1) // 1 persistent reference 121 runtime.SetFinalizer(p, (*Process).Release) 122 return p 123 } 124 125 func newDoneProcess(pid int) *Process { 126 p := &Process{ 127 Pid: pid, 128 mode: modeHandle, 129 // N.B Since we set statusDone, handle will never actually be 130 // used, so its value doesn't matter. 131 } 132 p.state.Store(uint64(statusDone)) // No persistent reference, as there is no handle. 133 runtime.SetFinalizer(p, (*Process).Release) 134 return p 135 } 136 137 func (p *Process) handleTransientAcquire() (uintptr, processStatus) { 138 if p.mode != modeHandle { 139 panic("handleTransientAcquire called in invalid mode") 140 } 141 142 for { 143 refs := p.state.Load() 144 if refs&processStatusMask != 0 { 145 return 0, processStatus(refs & processStatusMask) 146 } 147 new := refs + 1 148 if !p.state.CompareAndSwap(refs, new) { 149 continue 150 } 151 return p.handle, statusOK 152 } 153 } 154 155 func (p *Process) handleTransientRelease() { 156 if p.mode != modeHandle { 157 panic("handleTransientRelease called in invalid mode") 158 } 159 160 for { 161 state := p.state.Load() 162 refs := state &^ processStatusMask 163 status := processStatus(state & processStatusMask) 164 if refs == 0 { 165 // This should never happen because 166 // handleTransientRelease is always paired with 167 // handleTransientAcquire. 168 panic("release of handle with refcount 0") 169 } 170 if refs == 1 && status == statusOK { 171 // Process holds a persistent reference and always sets 172 // a status when releasing that reference 173 // (handlePersistentRelease). Thus something has gone 174 // wrong if this is the last release but a status has 175 // not always been set. 176 panic("final release of handle without processStatus") 177 } 178 new := state - 1 179 if !p.state.CompareAndSwap(state, new) { 180 continue 181 } 182 if new&^processStatusMask == 0 { 183 p.closeHandle() 184 } 185 return 186 } 187 } 188 189 // Drop the Process' persistent reference on the handle, deactivating future 190 // Wait/Signal calls with the passed reason. 191 // 192 // Returns the status prior to this call. If this is not statusOK, then the 193 // reference was not dropped or status changed. 194 func (p *Process) handlePersistentRelease(reason processStatus) processStatus { 195 if p.mode != modeHandle { 196 panic("handlePersistentRelease called in invalid mode") 197 } 198 199 for { 200 refs := p.state.Load() 201 status := processStatus(refs & processStatusMask) 202 if status != statusOK { 203 // Both Release and successful Wait will drop the 204 // Process' persistent reference on the handle. We 205 // can't allow concurrent calls to drop the reference 206 // twice, so we use the status as a guard to ensure the 207 // reference is dropped exactly once. 208 return status 209 } 210 if refs == 0 { 211 // This should never happen because dropping the 212 // persistent reference always sets a status. 213 panic("release of handle with refcount 0") 214 } 215 new := (refs - 1) | uint64(reason) 216 if !p.state.CompareAndSwap(refs, new) { 217 continue 218 } 219 if new&^processStatusMask == 0 { 220 p.closeHandle() 221 } 222 return status 223 } 224 } 225 226 func (p *Process) pidStatus() processStatus { 227 if p.mode != modePID { 228 panic("pidStatus called in invalid mode") 229 } 230 231 return processStatus(p.state.Load()) 232 } 233 234 func (p *Process) pidDeactivate(reason processStatus) { 235 if p.mode != modePID { 236 panic("pidDeactivate called in invalid mode") 237 } 238 239 // Both Release and successful Wait will deactivate the PID. Only one 240 // of those should win, so nothing left to do here if the compare 241 // fails. 242 // 243 // N.B. This means that results can be inconsistent. e.g., with a 244 // racing Release and Wait, Wait may successfully wait on the process, 245 // returning the wait status, while future calls error with "process 246 // released" rather than "process done". 247 p.state.CompareAndSwap(0, uint64(reason)) 248 } 249 250 // ProcAttr holds the attributes that will be applied to a new process 251 // started by StartProcess. 252 type ProcAttr struct { 253 // If Dir is non-empty, the child changes into the directory before 254 // creating the process. 255 Dir string 256 // If Env is non-nil, it gives the environment variables for the 257 // new process in the form returned by Environ. 258 // If it is nil, the result of Environ will be used. 259 Env []string 260 // Files specifies the open files inherited by the new process. The 261 // first three entries correspond to standard input, standard output, and 262 // standard error. An implementation may support additional entries, 263 // depending on the underlying operating system. A nil entry corresponds 264 // to that file being closed when the process starts. 265 // On Unix systems, StartProcess will change these File values 266 // to blocking mode, which means that SetDeadline will stop working 267 // and calling Close will not interrupt a Read or Write. 268 Files []*File 269 270 // Operating system-specific process creation attributes. 271 // Note that setting this field means that your program 272 // may not execute properly or even compile on some 273 // operating systems. 274 Sys *syscall.SysProcAttr 275 } 276 277 // A Signal represents an operating system signal. 278 // The usual underlying implementation is operating system-dependent: 279 // on Unix it is syscall.Signal. 280 type Signal interface { 281 String() string 282 Signal() // to distinguish from other Stringers 283 } 284 285 // Getpid returns the process id of the caller. 286 func Getpid() int { return syscall.Getpid() } 287 288 // Getppid returns the process id of the caller's parent. 289 func Getppid() int { return syscall.Getppid() } 290 291 // FindProcess looks for a running process by its pid. 292 // 293 // The [Process] it returns can be used to obtain information 294 // about the underlying operating system process. 295 // 296 // On Unix systems, FindProcess always succeeds and returns a Process 297 // for the given pid, regardless of whether the process exists. To test whether 298 // the process actually exists, see whether p.Signal(syscall.Signal(0)) reports 299 // an error. 300 func FindProcess(pid int) (*Process, error) { 301 return findProcess(pid) 302 } 303 304 // StartProcess starts a new process with the program, arguments and attributes 305 // specified by name, argv and attr. The argv slice will become [os.Args] in the 306 // new process, so it normally starts with the program name. 307 // 308 // If the calling goroutine has locked the operating system thread 309 // with [runtime.LockOSThread] and modified any inheritable OS-level 310 // thread state (for example, Linux or Plan 9 name spaces), the new 311 // process will inherit the caller's thread state. 312 // 313 // StartProcess is a low-level interface. The [os/exec] package provides 314 // higher-level interfaces. 315 // 316 // If there is an error, it will be of type [*PathError]. 317 func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) { 318 testlog.Open(name) 319 return startProcess(name, argv, attr) 320 } 321 322 // Release releases any resources associated with the [Process] p, 323 // rendering it unusable in the future. 324 // Release only needs to be called if [Process.Wait] is not. 325 func (p *Process) Release() error { 326 // Note to future authors: the Release API is cursed. 327 // 328 // On Unix and Plan 9, Release sets p.Pid = -1. This is the only part of the 329 // Process API that is not thread-safe, but it can't be changed now. 330 // 331 // On Windows, Release does _not_ modify p.Pid. 332 // 333 // On Windows, Wait calls Release after successfully waiting to 334 // proactively clean up resources. 335 // 336 // On Unix and Plan 9, Wait also proactively cleans up resources, but 337 // can not call Release, as Wait does not set p.Pid = -1. 338 // 339 // On Unix and Plan 9, calling Release a second time has no effect. 340 // 341 // On Windows, calling Release a second time returns EINVAL. 342 return p.release() 343 } 344 345 // Kill causes the [Process] to exit immediately. Kill does not wait until 346 // the Process has actually exited. This only kills the Process itself, 347 // not any other processes it may have started. 348 func (p *Process) Kill() error { 349 return p.kill() 350 } 351 352 // Wait waits for the [Process] to exit, and then returns a 353 // ProcessState describing its status and an error, if any. 354 // Wait releases any resources associated with the Process. 355 // On most operating systems, the Process must be a child 356 // of the current process or an error will be returned. 357 func (p *Process) Wait() (*ProcessState, error) { 358 return p.wait() 359 } 360 361 // Signal sends a signal to the [Process]. 362 // Sending [Interrupt] on Windows is not implemented. 363 func (p *Process) Signal(sig Signal) error { 364 return p.signal(sig) 365 } 366 367 // UserTime returns the user CPU time of the exited process and its children. 368 func (p *ProcessState) UserTime() time.Duration { 369 return p.userTime() 370 } 371 372 // SystemTime returns the system CPU time of the exited process and its children. 373 func (p *ProcessState) SystemTime() time.Duration { 374 return p.systemTime() 375 } 376 377 // Exited reports whether the program has exited. 378 // On Unix systems this reports true if the program exited due to calling exit, 379 // but false if the program terminated due to a signal. 380 func (p *ProcessState) Exited() bool { 381 return p.exited() 382 } 383 384 // Success reports whether the program exited successfully, 385 // such as with exit status 0 on Unix. 386 func (p *ProcessState) Success() bool { 387 return p.success() 388 } 389 390 // Sys returns system-dependent exit information about 391 // the process. Convert it to the appropriate underlying 392 // type, such as [syscall.WaitStatus] on Unix, to access its contents. 393 func (p *ProcessState) Sys() any { 394 return p.sys() 395 } 396 397 // SysUsage returns system-dependent resource usage information about 398 // the exited process. Convert it to the appropriate underlying 399 // type, such as [*syscall.Rusage] on Unix, to access its contents. 400 // (On Unix, *syscall.Rusage matches struct rusage as defined in the 401 // getrusage(2) manual page.) 402 func (p *ProcessState) SysUsage() any { 403 return p.sysUsage() 404 } 405