osproc: added a better version of waitForExit for Haiku (#13938)

Also modified tosprocterminate to verify waitForExit implementations.
This commit is contained in:
alaviss 2020-04-10 07:34:52 +00:00 • committed by GitHub
commit 5f6962337d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 6 deletions

View file

@ -1167,6 +1167,67 @@ elif not defined(useNimRtl):
discard posix.close(kqFD) discard posix.close(kqFD)
result = exitStatusLikeShell(p.exitStatus) result = exitStatusLikeShell(p.exitStatus)
elif defined(haiku):
const
B_OBJECT_TYPE_THREAD = 3
B_EVENT_INVALID = 0x1000
B_RELATIVE_TIMEOUT = 0x8
type
ObjectWaitInfo {.importc: "object_wait_info", header: "OS.h".} = object
obj {.importc: "object".}: int32
typ {.importc: "type".}: uint16
events: uint16
proc waitForObjects(infos: ptr ObjectWaitInfo, numInfos: cint, flags: uint32,
timeout: int64): clong
{.importc: "wait_for_objects_etc", header: "OS.h".}
proc waitForExit(p: Process, timeout: int = -1): int =
if p.exitFlag:
return exitStatusLikeShell(p.exitStatus)
if timeout == -1:
var status: cint = 1
if waitpid(p.id, status, 0) < 0:
raiseOSError(osLastError())
p.exitFlag = true
p.exitStatus = status
else:
var info = ObjectWaitInfo(
obj: p.id, # Haiku's PID is actually the main thread ID.
typ: B_OBJECT_TYPE_THREAD,
events: B_EVENT_INVALID # notify when the thread die.
)
while true:
var status: cint = 1
let count = waitForObjects(addr info, 1, B_RELATIVE_TIMEOUT, timeout)
if count < 0:
let err = count.cint
if err == ETIMEDOUT:
# timeout expired, so we try to kill the process
if posix.kill(p.id, SIGKILL) == -1:
raiseOSError(osLastError())
if waitpid(p.id, status, 0) < 0:
raiseOSError(osLastError())
p.exitFlag = true
p.exitStatus = status
break
elif err != EINTR:
raiseOSError(err.OSErrorCode)
elif count > 0:
if waitpid(p.id, status, 0) < 0:
raiseOSError(osLastError())
p.exitFlag = true
p.exitStatus = status
break
else:
doAssert false, "unreachable!"
result = exitStatusLikeShell(p.exitStatus)
else: else:
import times import times

View file

@ -1,8 +1,10 @@
discard """ discard """
outputsub: "SUCCESS" cmd: "nim $target $options -r $file"
targets: "c cpp"
matrix: "--threads:on; "
""" """
import os, osproc import os, osproc, times, std / monotimes
when defined(Windows): when defined(Windows):
const ProgramWhichDoesNotEnd = "notepad" const ProgramWhichDoesNotEnd = "notepad"
@ -19,7 +21,21 @@ while process.running() and TimeToWait > 0:
sleep(100) sleep(100)
TimeToWait = TimeToWait - 100 TimeToWait = TimeToWait - 100
if process.running(): doAssert not process.running()
echo("FAILED") echo("stopped process")
else:
echo("SUCCESS") process.close()
echo("starting " & ProgramWhichDoesNotEnd)
process = startProcess(ProgramWhichDoesNotEnd)
echo("process should be stopped after 2s")
let start = getMonoTime()
discard process.waitForExit(2000)
let took = getMonoTime() - start
doAssert not process.running()
# some additional time to account for overhead
doAssert took < initDuration(seconds = 3)
echo("stopped process after ", took)