68 lines
2.4 KiB
Plaintext
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
|