Merge pull request #4828 from jfhg/unify_waitpid_handling
Unify waitpid handling
This commit is contained in:
commit
f46168d654
3 changed files with 57 additions and 32 deletions
|
|
@ -48,7 +48,7 @@ type
|
||||||
inHandle, outHandle, errHandle: FileHandle
|
inHandle, outHandle, errHandle: FileHandle
|
||||||
inStream, outStream, errStream: Stream
|
inStream, outStream, errStream: Stream
|
||||||
id: Pid
|
id: Pid
|
||||||
exitCode: cint
|
exitStatus: cint
|
||||||
options: set[ProcessOption]
|
options: set[ProcessOption]
|
||||||
|
|
||||||
Process* = ref ProcessObj ## represents an operating system process
|
Process* = ref ProcessObj ## represents an operating system process
|
||||||
|
|
@ -731,7 +731,7 @@ elif not defined(useNimRtl):
|
||||||
pStdin, pStdout, pStderr: array[0..1, cint]
|
pStdin, pStdout, pStderr: array[0..1, cint]
|
||||||
new(result)
|
new(result)
|
||||||
result.options = options
|
result.options = options
|
||||||
result.exitCode = -3 # for ``waitForExit``
|
result.exitStatus = -3 # for ``waitForExit``
|
||||||
if poParentStreams notin options:
|
if poParentStreams notin options:
|
||||||
if pipe(pStdin) != 0'i32 or pipe(pStdout) != 0'i32 or
|
if pipe(pStdin) != 0'i32 or pipe(pStdout) != 0'i32 or
|
||||||
pipe(pStderr) != 0'i32:
|
pipe(pStderr) != 0'i32:
|
||||||
|
|
@ -957,13 +957,10 @@ elif not defined(useNimRtl):
|
||||||
|
|
||||||
proc running(p: Process): bool =
|
proc running(p: Process): bool =
|
||||||
var ret : int
|
var ret : int
|
||||||
when not defined(freebsd):
|
var status : cint = 1
|
||||||
ret = waitpid(p.id, p.exitCode, WNOHANG)
|
ret = waitpid(p.id, status, WNOHANG)
|
||||||
else:
|
if WIFEXITED(status):
|
||||||
var status : cint = 1
|
p.exitStatus = status
|
||||||
ret = waitpid(p.id, status, WNOHANG)
|
|
||||||
if WIFEXITED(status):
|
|
||||||
p.exitCode = status
|
|
||||||
if ret == 0: return true # Can't establish status. Assume running.
|
if ret == 0: return true # Can't establish status. Assume running.
|
||||||
result = ret == int(p.id)
|
result = ret == int(p.id)
|
||||||
|
|
||||||
|
|
@ -980,11 +977,12 @@ elif not defined(useNimRtl):
|
||||||
import kqueue, times
|
import kqueue, times
|
||||||
|
|
||||||
proc waitForExit(p: Process, timeout: int = -1): int =
|
proc waitForExit(p: Process, timeout: int = -1): int =
|
||||||
if p.exitCode != -3: return p.exitCode
|
if p.exitStatus != -3: return int(p.exitStatus) shr 8
|
||||||
if timeout == -1:
|
if timeout == -1:
|
||||||
if waitpid(p.id, p.exitCode, 0) < 0:
|
var status : cint = 1
|
||||||
p.exitCode = -3
|
if waitpid(p.id, status, 0) < 0:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
p.exitStatus = status
|
||||||
else:
|
else:
|
||||||
var kqFD = kqueue()
|
var kqFD = kqueue()
|
||||||
if kqFD == -1:
|
if kqFD == -1:
|
||||||
|
|
@ -1004,6 +1002,7 @@ elif not defined(useNimRtl):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while true:
|
while true:
|
||||||
|
var status : cint = 1
|
||||||
var count = kevent(kqFD, addr(kevIn), 1, addr(kevOut), 1,
|
var count = kevent(kqFD, addr(kevIn), 1, addr(kevOut), 1,
|
||||||
addr(tmspec))
|
addr(tmspec))
|
||||||
if count < 0:
|
if count < 0:
|
||||||
|
|
@ -1014,22 +1013,22 @@ elif not defined(useNimRtl):
|
||||||
# timeout expired, so we trying to kill process
|
# timeout expired, so we trying to kill process
|
||||||
if posix.kill(p.id, SIGKILL) == -1:
|
if posix.kill(p.id, SIGKILL) == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
if waitpid(p.id, p.exitCode, 0) < 0:
|
if waitpid(p.id, status, 0) < 0:
|
||||||
p.exitCode = -3
|
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
p.exitStatus = status
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if kevOut.ident == p.id.uint and kevOut.filter == EVFILT_PROC:
|
if kevOut.ident == p.id.uint and kevOut.filter == EVFILT_PROC:
|
||||||
if waitpid(p.id, p.exitCode, 0) < 0:
|
if waitpid(p.id, status, 0) < 0:
|
||||||
p.exitCode = -3
|
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
p.exitStatus = status
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
finally:
|
finally:
|
||||||
discard posix.close(kqFD)
|
discard posix.close(kqFD)
|
||||||
|
|
||||||
result = int(p.exitCode) shr 8
|
result = int(p.exitStatus) shr 8
|
||||||
else:
|
else:
|
||||||
import times
|
import times
|
||||||
|
|
||||||
|
|
@ -1061,15 +1060,16 @@ elif not defined(useNimRtl):
|
||||||
s.tv_sec = b.tv_sec
|
s.tv_sec = b.tv_sec
|
||||||
s.tv_nsec = b.tv_nsec
|
s.tv_nsec = b.tv_nsec
|
||||||
|
|
||||||
#if waitPid(p.id, p.exitCode, 0) == int(p.id):
|
#if waitPid(p.id, p.exitStatus, 0) == int(p.id):
|
||||||
# ``waitPid`` fails if the process is not running anymore. But then
|
# ``waitPid`` fails if the process is not running anymore. But then
|
||||||
# ``running`` probably set ``p.exitCode`` for us. Since ``p.exitCode`` is
|
# ``running`` probably set ``p.exitStatus`` for us. Since ``p.exitStatus`` is
|
||||||
# initialized with -3, wrong success exit codes are prevented.
|
# initialized with -3, wrong success exit codes are prevented.
|
||||||
if p.exitCode != -3: return p.exitCode
|
if p.exitStatus != -3: return int(p.exitStatus) shr 8
|
||||||
if timeout == -1:
|
if timeout == -1:
|
||||||
if waitpid(p.id, p.exitCode, 0) < 0:
|
var status : cint = 1
|
||||||
p.exitCode = -3
|
if waitpid(p.id, status, 0) < 0:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
p.exitStatus = status
|
||||||
else:
|
else:
|
||||||
var nmask, omask: Sigset
|
var nmask, omask: Sigset
|
||||||
var sinfo: SigInfo
|
var sinfo: SigInfo
|
||||||
|
|
@ -1100,9 +1100,10 @@ elif not defined(useNimRtl):
|
||||||
let res = sigtimedwait(nmask, sinfo, tmspec)
|
let res = sigtimedwait(nmask, sinfo, tmspec)
|
||||||
if res == SIGCHLD:
|
if res == SIGCHLD:
|
||||||
if sinfo.si_pid == p.id:
|
if sinfo.si_pid == p.id:
|
||||||
if waitpid(p.id, p.exitCode, 0) < 0:
|
var status : cint = 1
|
||||||
p.exitCode = -3
|
if waitpid(p.id, status, 0) < 0:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
p.exitStatus = status
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# we have SIGCHLD, but not for process we are waiting,
|
# we have SIGCHLD, but not for process we are waiting,
|
||||||
|
|
@ -1122,9 +1123,10 @@ elif not defined(useNimRtl):
|
||||||
# timeout expired, so we trying to kill process
|
# timeout expired, so we trying to kill process
|
||||||
if posix.kill(p.id, SIGKILL) == -1:
|
if posix.kill(p.id, SIGKILL) == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
if waitpid(p.id, p.exitCode, 0) < 0:
|
var status : cint = 1
|
||||||
p.exitCode = -3
|
if waitpid(p.id, status, 0) < 0:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
p.exitStatus = status
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raiseOSError(err)
|
raiseOSError(err)
|
||||||
|
|
@ -1136,17 +1138,19 @@ elif not defined(useNimRtl):
|
||||||
if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
|
if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
result = int(p.exitCode) shr 8
|
result = int(p.exitStatus) shr 8
|
||||||
|
|
||||||
proc peekExitCode(p: Process): int =
|
proc peekExitCode(p: Process): int =
|
||||||
if p.exitCode != -3: return p.exitCode
|
var status : cint = 1
|
||||||
var ret = waitpid(p.id, p.exitCode, WNOHANG)
|
if p.exitStatus != -3: return int(p.exitStatus) shr 8
|
||||||
|
var ret = waitpid(p.id, status, WNOHANG)
|
||||||
var b = ret == int(p.id)
|
var b = ret == int(p.id)
|
||||||
if b: result = -1
|
if b: result = -1
|
||||||
if not WIFEXITED(p.exitCode):
|
if WIFEXITED(status):
|
||||||
p.exitCode = -3
|
p.exitStatus = status
|
||||||
|
result = p.exitStatus.int shr 8
|
||||||
|
else:
|
||||||
result = -1
|
result = -1
|
||||||
else: result = p.exitCode.int shr 8
|
|
||||||
|
|
||||||
proc createStream(stream: var Stream, handle: var FileHandle,
|
proc createStream(stream: var Stream, handle: var FileHandle,
|
||||||
fileMode: FileMode) =
|
fileMode: FileMode) =
|
||||||
|
|
|
||||||
3
tests/osproc/tafalse.nim
Normal file
3
tests/osproc/tafalse.nim
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
# 'tafalse.nim' to ensure it is compiled before texitcode.nim
|
||||||
|
import system
|
||||||
|
quit(QuitFailure)
|
||||||
18
tests/osproc/texitcode.nim
Normal file
18
tests/osproc/texitcode.nim
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
discard """
|
||||||
|
file: "texitcode.nim"
|
||||||
|
output: ""
|
||||||
|
"""
|
||||||
|
import osproc, os
|
||||||
|
|
||||||
|
const filename = when defined(Windows): "tafalse.exe" else: "tafalse"
|
||||||
|
let dir = getCurrentDir() / "tests" / "osproc"
|
||||||
|
doAssert fileExists(dir / filename)
|
||||||
|
|
||||||
|
var p = startProcess(filename, dir)
|
||||||
|
doAssert(waitForExit(p) == QuitFailure)
|
||||||
|
|
||||||
|
p = startProcess(filename, dir)
|
||||||
|
var running = true
|
||||||
|
while running:
|
||||||
|
running = running(p)
|
||||||
|
doAssert(waitForExit(p) == QuitFailure)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue