mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 12:07:51 +00:00
WIFSIGNALED means process has exited too (with a bang!) (#5678)
This commit is contained in:
committed by
Andreas Rumpf
parent
40f79e6cdd
commit
0055729755
@@ -97,15 +97,6 @@ when not defined(macosx):
|
||||
## Second-granularity time of last status change.
|
||||
result = s.st_ctim.tv_sec
|
||||
|
||||
proc WIFCONTINUED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child has been continued.
|
||||
proc WIFEXITED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child exited normally.
|
||||
proc WIFSIGNALED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child exited due to uncaught signal.
|
||||
proc WIFSTOPPED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child is currently stopped.
|
||||
|
||||
when hasAioH:
|
||||
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}
|
||||
|
||||
@@ -602,3 +602,12 @@ var
|
||||
include posix_linux_amd64_consts
|
||||
|
||||
const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE!
|
||||
|
||||
# <sys/wait.h>
|
||||
proc WEXITSTATUS*(s: cint): cint = (s and 0xff00) shr 8
|
||||
proc WTERMSIG*(s:cint): cint = s and 0x7f
|
||||
proc WSTOPSIG*(s:cint): cint = WEXITSTATUS(s)
|
||||
proc WIFEXITED*(s:cint) : bool = WTERMSIG(s) == 0
|
||||
proc WIFSIGNALED*(s:cint) : bool = (cast[int8]((s and 0x7f) + 1) shr 1) > 0
|
||||
proc WIFSTOPPED*(s:cint) : bool = (s and 0xff) == 0x7f
|
||||
proc WIFCONTINUED*(s:cint) : bool = s == W_CONTINUED
|
||||
|
||||
@@ -611,3 +611,18 @@ when hasSpawnH:
|
||||
# OR'ing of flags:
|
||||
const POSIX_SPAWN_USEVFORK* = cint(0)
|
||||
|
||||
# <sys/wait.h>
|
||||
proc WEXITSTATUS*(s: cint): cint {.importc, header: "<sys/wait.h>".}
|
||||
## Exit code, iff WIFEXITED(s)
|
||||
proc WTERMSIG*(s: cint): cint {.importc, header: "<sys/wait.h>".}
|
||||
## Termination signal, iff WIFSIGNALED(s)
|
||||
proc WSTOPSIG*(s: cint): cint {.importc, header: "<sys/wait.h>".}
|
||||
## Stop signal, iff WIFSTOPPED(s)
|
||||
proc WIFEXITED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child exited normally.
|
||||
proc WIFSIGNALED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child exited due to uncaught signal.
|
||||
proc WIFSTOPPED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child is currently stopped.
|
||||
proc WIFCONTINUED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
|
||||
## True if child has been continued.
|
||||
|
||||
@@ -209,9 +209,16 @@ proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
|
||||
##
|
||||
## **Warning**: Be careful when using waitForExit for processes created without
|
||||
## poParentStreams because they may fill output buffers, causing deadlock.
|
||||
##
|
||||
## On posix, if the process has exited because of a signal, 128 + signal
|
||||
## number will be returned.
|
||||
|
||||
|
||||
proc peekExitCode*(p: Process): int {.tags: [].}
|
||||
## return -1 if the process is still running. Otherwise the process' exit code
|
||||
##
|
||||
## On posix, if the process has exited because of a signal, 128 + signal
|
||||
## number will be returned.
|
||||
|
||||
proc inputStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [].}
|
||||
## returns ``p``'s input stream for writing to.
|
||||
@@ -679,6 +686,16 @@ elif not defined(useNimRtl):
|
||||
readIdx = 0
|
||||
writeIdx = 1
|
||||
|
||||
proc isExitStatus(status: cint): bool =
|
||||
WIFEXITED(status) or WIFSIGNALED(status)
|
||||
|
||||
proc exitStatus(status: cint): cint =
|
||||
if WIFSIGNALED(status):
|
||||
# like the shell!
|
||||
128 + WTERMSIG(status)
|
||||
else:
|
||||
WEXITSTATUS(status)
|
||||
|
||||
proc envToCStringArray(t: StringTableRef): cstringArray =
|
||||
result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring)))
|
||||
var i = 0
|
||||
@@ -967,7 +984,7 @@ elif not defined(useNimRtl):
|
||||
var status : cint = 1
|
||||
ret = waitpid(p.id, status, WNOHANG)
|
||||
if ret == int(p.id):
|
||||
if WIFEXITED(status):
|
||||
if isExitStatus(status):
|
||||
p.exitStatus = status
|
||||
return false
|
||||
else:
|
||||
@@ -990,7 +1007,9 @@ elif not defined(useNimRtl):
|
||||
import kqueue, times
|
||||
|
||||
proc waitForExit(p: Process, timeout: int = -1): int =
|
||||
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8)
|
||||
if p.exitStatus != -3:
|
||||
return exitStatus(p.exitStatus)
|
||||
|
||||
if timeout == -1:
|
||||
var status : cint = 1
|
||||
if waitpid(p.id, status, 0) < 0:
|
||||
@@ -1041,7 +1060,7 @@ elif not defined(useNimRtl):
|
||||
finally:
|
||||
discard posix.close(kqFD)
|
||||
|
||||
result = ((p.exitStatus and 0xFF00) shr 8)
|
||||
result = exitStatus(p.exitStatus)
|
||||
else:
|
||||
import times
|
||||
|
||||
@@ -1077,7 +1096,9 @@ elif not defined(useNimRtl):
|
||||
# ``waitPid`` fails if the process is not running anymore. But then
|
||||
# ``running`` probably set ``p.exitStatus`` for us. Since ``p.exitStatus`` is
|
||||
# initialized with -3, wrong success exit codes are prevented.
|
||||
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8)
|
||||
if p.exitStatus != -3:
|
||||
return exitStatus(p.exitStatus)
|
||||
|
||||
if timeout == -1:
|
||||
var status : cint = 1
|
||||
if waitpid(p.id, status, 0) < 0:
|
||||
@@ -1151,17 +1172,19 @@ elif not defined(useNimRtl):
|
||||
if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
|
||||
raiseOSError(osLastError())
|
||||
|
||||
result = ((p.exitStatus and 0xFF00) shr 8)
|
||||
result = exitStatus(p.exitStatus)
|
||||
|
||||
proc peekExitCode(p: Process): int =
|
||||
var status = cint(0)
|
||||
result = -1
|
||||
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8)
|
||||
if p.exitStatus != -3:
|
||||
return exitStatus(p.exitStatus)
|
||||
|
||||
var ret = waitpid(p.id, status, WNOHANG)
|
||||
if ret > 0:
|
||||
if WIFEXITED(status):
|
||||
if isExitStatus(status):
|
||||
p.exitStatus = status
|
||||
result = (status and 0xFF00) shr 8
|
||||
result = exitStatus(status)
|
||||
|
||||
proc createStream(stream: var Stream, handle: var FileHandle,
|
||||
fileMode: FileMode) =
|
||||
@@ -1189,7 +1212,8 @@ elif not defined(useNimRtl):
|
||||
|
||||
proc execCmd(command: string): int =
|
||||
when defined(linux):
|
||||
result = csystem(command) shr 8
|
||||
let tmp = csystem(command)
|
||||
result = if tmp == -1: tmp else: exitStatus(tmp)
|
||||
else:
|
||||
result = csystem(command)
|
||||
|
||||
|
||||
36
tests/osproc/texitsignal.nim
Normal file
36
tests/osproc/texitsignal.nim
Normal file
@@ -0,0 +1,36 @@
|
||||
discard """
|
||||
output: '''true
|
||||
true'''
|
||||
targets: "c"
|
||||
"""
|
||||
|
||||
import os, osproc
|
||||
when not defined(windows):
|
||||
import posix
|
||||
|
||||
# Checks that the environment is passed correctly in startProcess
|
||||
# To do that launches a copy of itself with a new environment.
|
||||
|
||||
if paramCount() == 0:
|
||||
# Parent process
|
||||
|
||||
let p = startProcess(
|
||||
getAppFilename(),
|
||||
args = @["child"],
|
||||
options = {poStdErrToStdOut, poUsePath, poParentStreams}
|
||||
)
|
||||
|
||||
echo p.running()
|
||||
|
||||
p.kill()
|
||||
|
||||
when defined(windows):
|
||||
# windows kill happens using TerminateProcess(h, 0), so we should get a
|
||||
# 0 here
|
||||
echo p.waitForExit() == 0
|
||||
else:
|
||||
# on posix (non-windows), kill sends SIGKILL
|
||||
echo p.waitForExit() == 128 + SIGKILL
|
||||
|
||||
else:
|
||||
sleep(5000) # should get killed before this
|
||||
@@ -56,6 +56,8 @@ Changes affecting backwards compatibility
|
||||
checks. When fields within case objects are initialiazed, the compiler will
|
||||
now demand that the respective discriminator field has a matching known
|
||||
compile-time value.
|
||||
- On posix, the results of `waitForExit`, `peekExitCode`, `execCmd` will return
|
||||
128 + signal number if the application terminates via signal.
|
||||
|
||||
Library Additions
|
||||
-----------------
|
||||
|
||||
Reference in New Issue
Block a user