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.
5 //go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows
11 "internal/syscall/execenv"
16 // The only signal values guaranteed to be present in the os package on all
17 // systems are os.Interrupt (send the process an interrupt) and os.Kill (force
18 // the process to exit). On Windows, sending os.Interrupt to a process with
19 // os.Process.Signal is not implemented; it will return an error instead of
22 Interrupt Signal
= syscall
.SIGINT
23 Kill Signal
= syscall
.SIGKILL
26 func startProcess(name
string, argv
[]string, attr
*ProcAttr
) (p
*Process
, err error
) {
27 // If there is no SysProcAttr (ie. no Chroot or changed
28 // UID/GID), double-check existence of the directory we want
29 // to chdir into. We can make the error clearer this way.
30 if attr
!= nil && attr
.Sys
== nil && attr
.Dir
!= "" {
31 if _
, err
:= Stat(attr
.Dir
); err
!= nil {
32 pe
:= err
.(*PathError
)
38 sysattr
:= &syscall
.ProcAttr
{
43 if sysattr
.Env
== nil {
44 sysattr
.Env
, err
= execenv
.Default(sysattr
.Sys
)
49 sysattr
.Files
= make([]uintptr, 0, len(attr
.Files
))
50 for _
, f
:= range attr
.Files
{
51 sysattr
.Files
= append(sysattr
.Files
, f
.Fd())
54 pid
, h
, e
:= syscall
.StartProcess(name
, argv
, sysattr
)
56 // Make sure we don't run the finalizers of attr.Files.
57 runtime
.KeepAlive(attr
)
60 return nil, &PathError
{Op
: "fork/exec", Path
: name
, Err
: e
}
63 return newProcess(pid
, h
), nil
66 func (p
*Process
) kill() error
{
70 // ProcessState stores information about a process, as reported by Wait.
71 type ProcessState
struct {
72 pid
int // The process's id.
73 status syscall
.WaitStatus
// System-dependent status info.
74 rusage
*syscall
.Rusage
77 // Pid returns the process id of the exited process.
78 func (p
*ProcessState
) Pid() int {
82 func (p
*ProcessState
) exited() bool {
83 return p
.status
.Exited()
86 func (p
*ProcessState
) success() bool {
87 return p
.status
.ExitStatus() == 0
90 func (p
*ProcessState
) sys() any
{
94 func (p
*ProcessState
) sysUsage() any
{
98 func (p
*ProcessState
) String() string {
102 status
:= p
.Sys().(syscall
.WaitStatus
)
105 case status
.Exited():
106 code
:= status
.ExitStatus()
107 if runtime
.GOOS
== "windows" && uint(code
) >= 1<<16 { // windows uses large hex numbers
108 res
= "exit status " + uitox(uint(code
))
109 } else { // unix systems use small decimal integers
110 res
= "exit status " + itoa
.Itoa(code
) // unix
112 case status
.Signaled():
113 res
= "signal: " + status
.Signal().String()
114 case status
.Stopped():
115 res
= "stop signal: " + status
.StopSignal().String()
116 if status
.StopSignal() == syscall
.SIGTRAP
&& status
.TrapCause() != 0 {
117 res
+= " (trap " + itoa
.Itoa(status
.TrapCause()) + ")"
119 case status
.Continued():
122 if status
.CoreDump() {
123 res
+= " (core dumped)"
128 // ExitCode returns the exit code of the exited process, or -1
129 // if the process hasn't exited or was terminated by a signal.
130 func (p
*ProcessState
) ExitCode() int {
131 // return -1 if the process hasn't started.
135 return p
.status
.ExitStatus()