65 lines
1.6 KiB
Plaintext
65 lines
1.6 KiB
Plaintext
## the exit handle: waiting for a child to terminate with no polling at all.
|
|
##
|
|
## sys.popen's slot 4 is a handle that becomes readable when the child exits,
|
|
## so it is waited on exactly like a pipe. Where the platform has no such
|
|
## facility the slot is nil and this test reports that it was skipped.
|
|
|
|
fun chk(ok msg) {
|
|
if ok { printf "OK: %s\n" msg } \
|
|
else { printf "ERROR: %s\n" msg }
|
|
}
|
|
|
|
iosem := (core.sem-new)
|
|
tmo := (core.sem-new)
|
|
sg := (core.semgr-new)
|
|
core.semgr-add sg iosem
|
|
core.semgr-add sg tmo
|
|
fin := (core.sem-new)
|
|
|
|
p := (sys.popen "sleep 1; exit 5" "r")
|
|
proc := (core.basicAt p 0)
|
|
xh := (core.basicAt p 4)
|
|
|
|
if (nil? xh) {
|
|
printf "OK: no exit handle on this platform - skipped\n"
|
|
sys.pclose proc
|
|
} \
|
|
else {
|
|
ticks := 0
|
|
status := -2
|
|
|
|
fun waiter() {
|
|
| s |
|
|
core.sem-signal tmo 20 0
|
|
core.sem-signal-on-input iosem xh
|
|
s := (core.semgr-wait sg)
|
|
core.sem-unsignal iosem
|
|
core.sem-unsignal tmo
|
|
if (eqv? s tmo) { status := -1 } \
|
|
else { status := (sys.pwait proc) }
|
|
core.sem-signal fin
|
|
return 0
|
|
}
|
|
|
|
fun ticker() {
|
|
## the waiter is parked on the exit handle by now; these ticks only
|
|
## happen if the VM went on scheduling instead of blocking
|
|
while (< ticks 4) {
|
|
ticks := (+ ticks 1)
|
|
core.yield
|
|
}
|
|
}
|
|
|
|
chk (integer? xh) "sys.popen hands back an exit handle"
|
|
core.fork waiter
|
|
core.fork ticker
|
|
core.sem-wait fin
|
|
|
|
chk (= ticks 4) "other coprocesses ran while the child was alive"
|
|
chk (= status 5) "the exit handle woke the waiter and the status was read"
|
|
|
|
## it belongs to the process handle, so pclose takes it away
|
|
sys.pclose proc
|
|
chk true "pclose released the exit handle with the group"
|
|
}
|