Files
hak/t/mux-03.hak

68 lines
2.4 KiB
Plaintext

## both directions bound to one descriptor, then one of them dropped
##
## Binding an input and an output semaphore to the same handle gives the VM a
## tuple with two directions. Unbinding one of them leaves the other in place,
## so delete_sem_from_sem_io_tuple() modifies the registration rather than
## removing it - vm_muxmod() instead of vm_muxdel(). Nothing else in the suite
## takes that path, so the per-direction event purge behind it is otherwise
## never executed.
##
## A pipe's write end is used because it is always writable, so the output
## semaphore has something to report; the input side is registered but never
## fires, which is fine - what matters is that both directions are registered.
fun chk(ok msg) {
if ok { printf "OK: %s\n" msg } \
else { printf "ERROR: %s\n" msg }
}
sg := (core.semgr-new)
isem := (core.sem-new)
osem := (core.sem-new)
tmo := (core.sem-new)
core.semgr-add sg isem
core.semgr-add sg osem
core.semgr-add sg tmo
p := (sys.pipe)
r := (core.basicAt p 0)
w := (core.basicAt p 1)
## one descriptor, two directions - the tuple now carries both
core.sem-signal-on-input isem w
core.sem-signal-on-output osem w
## drop only the input direction. the output registration must survive, and so
## must any event already reported for it
core.sem-unsignal isem
core.sem-signal tmo 5 0
s := (core.semgr-wait sg)
chk (eqv? s osem) "the surviving direction still reports after a partial unbind"
core.sem-unsignal tmo
## put the input direction back while the output one is still registered. this
## is the add branch of the modify path - the mirror of the drop above - and it
## has to leave the output registration alone.
core.sem-signal-on-input isem w
## now drop the output direction instead, keeping input. a write end is never
## readable, so with input alone nothing can report and the timer must win. if
## the modify path had left the output registration behind, its writability
## would be reported here and the timer would lose.
core.sem-unsignal osem
core.sem-signal tmo 0 300000000
s := (core.semgr-wait sg)
chk (eqv? s tmo) "the dropped direction stops reporting after a partial unbind"
core.sem-unsignal tmo
## and the full unbind from that state really removes the registration
core.sem-unsignal isem
core.sem-signal tmo 0 300000000
s := (core.semgr-wait sg)
chk (eqv? s tmo) "nothing reports once both directions are unbound"
core.sem-unsignal tmo
sys.close r
sys.close w