gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/abi/linux/wait.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package linux 16 17 import ( 18 "fmt" 19 ) 20 21 // Options for waitpid(2), wait4(2), and/or waitid(2), from 22 // include/uapi/linux/wait.h. 23 const ( 24 WNOHANG = 0x00000001 25 WUNTRACED = 0x00000002 26 WSTOPPED = WUNTRACED 27 WEXITED = 0x00000004 28 WCONTINUED = 0x00000008 29 WNOWAIT = 0x01000000 30 WNOTHREAD = 0x20000000 31 WALL = 0x40000000 32 WCLONE = 0x80000000 33 ) 34 35 // ID types for waitid(2), from include/uapi/linux/wait.h. 36 const ( 37 P_ALL = 0x0 38 P_PID = 0x1 39 P_PGID = 0x2 40 ) 41 42 // WaitStatus represents a thread status, as returned by the wait* family of 43 // syscalls. 44 type WaitStatus uint32 45 46 // WaitStatusExit returns a WaitStatus representing the given exit status. 47 func WaitStatusExit(status int32) WaitStatus { 48 return WaitStatus(uint32(status) << 8) 49 } 50 51 // WaitStatusTerminationSignal returns a WaitStatus representing termination by 52 // the given signal. 53 func WaitStatusTerminationSignal(sig Signal) WaitStatus { 54 return WaitStatus(uint32(sig)) 55 } 56 57 // WaitStatusStopped returns a WaitStatus representing stoppage by the given 58 // signal or ptrace trap code. 59 func WaitStatusStopped(code uint32) WaitStatus { 60 return WaitStatus(code<<8 | 0x7f) 61 } 62 63 // WaitStatusContinued returns a WaitStatus representing continuation by 64 // SIGCONT. 65 func WaitStatusContinued() WaitStatus { 66 return WaitStatus(0xffff) 67 } 68 69 // WithCoreDump returns a copy of ws that indicates that a core dump was 70 // generated. 71 // 72 // Preconditions: ws.Signaled(). 73 func (ws WaitStatus) WithCoreDump() WaitStatus { 74 return ws | 0x80 75 } 76 77 // Exited returns true if ws represents an exit status, consistent with 78 // WIFEXITED. 79 func (ws WaitStatus) Exited() bool { 80 return ws&0x7f == 0 81 } 82 83 // Signaled returns true if ws represents a termination by signal, consistent 84 // with WIFSIGNALED. 85 func (ws WaitStatus) Signaled() bool { 86 // ws&0x7f != 0 (exited) and ws&0x7f != 0x7f (stopped or continued) 87 return ((ws&0x7f)+1)>>1 != 0 88 } 89 90 // CoreDumped returns true if ws indicates that a core dump was produced, 91 // consistent with WCOREDUMP. 92 // 93 // Preconditions: ws.Signaled(). 94 func (ws WaitStatus) CoreDumped() bool { 95 return ws&0x80 != 0 96 } 97 98 // Stopped returns true if ws represents a stoppage, consistent with 99 // WIFSTOPPED. 100 func (ws WaitStatus) Stopped() bool { 101 return ws&0xff == 0x7f 102 } 103 104 // Continued returns true if ws represents a continuation by SIGCONT, 105 // consistent with WIFCONTINUED. 106 func (ws WaitStatus) Continued() bool { 107 return ws == 0xffff 108 } 109 110 // ExitStatus returns the lower 8 bits of the exit status represented by ws, 111 // consistent with WEXITSTATUS. 112 // 113 // Preconditions: ws.Exited(). 114 func (ws WaitStatus) ExitStatus() uint32 { 115 return uint32((ws & 0xff00) >> 8) 116 } 117 118 // TerminationSignal returns the termination signal represented by ws, 119 // consistent with WTERMSIG. 120 // 121 // Preconditions: ws.Signaled(). 122 func (ws WaitStatus) TerminationSignal() Signal { 123 return Signal(ws & 0x7f) 124 } 125 126 // StopSignal returns the stop signal represented by ws, consistent with 127 // WSTOPSIG. 128 // 129 // Preconditions: ws.Stopped(). 130 func (ws WaitStatus) StopSignal() Signal { 131 return Signal((ws & 0xff00) >> 8) 132 } 133 134 // PtraceEvent returns the PTRACE_EVENT_* field in ws. 135 // 136 // Preconditions: ws.Stopped(). 137 func (ws WaitStatus) PtraceEvent() uint32 { 138 return uint32(ws >> 16) 139 } 140 141 // String implements fmt.Stringer.String. 142 func (ws WaitStatus) String() string { 143 switch { 144 case ws.Exited(): 145 return fmt.Sprintf("exit status %d", ws.ExitStatus()) 146 case ws.Signaled(): 147 if ws.CoreDumped() { 148 return fmt.Sprintf("killed by signal %d (core dumped)", ws.TerminationSignal()) 149 } 150 return fmt.Sprintf("killed by signal %d", ws.TerminationSignal()) 151 case ws.Stopped(): 152 if ev := ws.PtraceEvent(); ev != 0 { 153 return fmt.Sprintf("stopped by signal %d (PTRACE_EVENT %d)", ws.StopSignal(), ev) 154 } 155 return fmt.Sprintf("stopped by signal %d", ws.StopSignal()) 156 case ws.Continued(): 157 return "continued" 158 default: 159 return fmt.Sprintf("unknown status %#x", uint32(ws)) 160 } 161 }