The patch here removes a terminated facet from its parent's
`facet-children` set only in a script, and only after all other
scripts enqueued as part of facet termination have executed without an
uncaught exception.
This means that, if (say) a stop script raises an uncaught exception,
it might have happened after some *but not all* scripts resulting from
calls to `retract-facet-assertions-and-subscriptions!` have already
executed. So some endpoints' assertions and subscriptions will have
been removed.
When the uncaught exception is caught by the handler in
`with-current-facet`, a call to `abandon-queued-work!` is made, which
discards queued scripts, including the remaining assertion-cleanup
scripts as well as the scripts for removing dead facets from their
parents' `facet-children` sets. It also (crucially) discards queued
patch actions, including those resulting from already-executed
assertion-cleanup scripts.
At this point, we have a facet tree with some dead facets still in it,
and no queued outbound patches. The assertions for the still-present
dead facets are still logically asserted.
Then, a call to `terminate-actor!` happens, which traverses the whole
tree enqueueing assertion-cleanup scripts. No user code is enqueued,
so (in principle) no exceptions can be signalled.
Once these `terminate-actor!`-enqueued scripts execute, a pending
patch exists that will remove all remaining endpoint assertions.
The remaining sticky point is the calls to `dataspace-unsubscribe!`.
Happily, these are idempotent because of the implementation in
`skeleton.rkt`.
Prior to this patch, terminating facets were removed early from their
parents' `facet-children` sets, meaning there was no way to find them
again to clean up if a failure occurred during a stop script.
Ideally, it'd be easy to see that the code is correct in this respect.
We're not there yet.
If:
- a field is used in an assertion of interest in facet A
- and that field changes
- to a value that causes the assertion of interest to overlap
with some facet B's assertion of interest
- and an assertion matching that interest was already known to the actor,
Then:
- previously, facet A would not be informed of the matching assertion
- but now, it is informed of the matching assertion.
This more or less only affects "on asserted" endpoints.
The change here should be written up as an erratum to chapter 5 in my
dissertation. Also, syndicate/js needs to be checked for the bug and
probably fixed in an analogous way.
Switch from synchronous to asynchronous UDP transmission, in case DNS
resolution takes a long time or fails. Specifically, in case of failure,
previously the UDP actor would crash, whereas now the packet is just
"dropped".
- New timestate `on-timeout` complementing `stop-when-timeout`
- IP layer avoids spurious reordering
- Demo HTTP server sends 4kB responses, for testing
- TCP now has something closer to proper sliding-window behavior
- TCP RTT estimator
- TCP now uses timestate driver rather than raw timer driver
- Many small TCP bugs found and fixed