tonyg / syndicate

syn·di·cate: a language for interactive programs
http://syndicate-lang.org/
GNU Lesser General Public License v3.0
152 stars 11 forks source link

LLL `demand-matcher` suffers from the same problems the HLL `during/spawn` used to #25

Open tonyg opened 7 years ago

tonyg commented 7 years ago

For example, in #21, we have that the port 6000 listener sticks around even when no longer wanted, because the change in demand happened before the listener could boot up fully. When it starts running, it monitors demand correctly, but demand for port 6000 has already vanished so it never gets any events at all.

The HLL during/spawn fixes this by allocating instance IDs and running a protocol between the during part and each spawned supply-instance. The LLL demand-matcher should probably do the same thing.

tonyg commented 7 years ago

Relevant comment from example-demand-matcher-glitch-bug.rkt:

;; Example showing the consequences of not honouring the requirement
;; of the current LLL demand-matcher that supply tasks must *reliably*
;; terminate when their demand is not present. In this case, demand
;; changes too quickly: it exists for long enough to start the task,
;; but is withdrawn before the task itself has a chance to detect it.
;; Because the task (as currently implemented) does not use the "learn
;; negative knowledge" pattern to detect the *absence* of some
;; assertion, it does not terminate as it is supposed to.
;;
;; Specifically, here, the port 6000 server is started, but by the
;; time it starts monitoring demand for its services, the demand is
;; already gone, replaced with demand for port 5999. This causes
;; connections to be accepted on port 6000 going nowhere.
;;
;; One "fix" is to use #:assertions to give the TCP listener actor
;; some initial interests, thus transferring responsibility
;; atomically. This has been implemented (in commit 2a0197b). However,
;; this doesn't completely eliminate all possible instances where
;; demand may change too quickly. See example-demand-matcher-glitch-bug2.rkt.
;;
;; Of course, the real "fix" is for the TCP listener actor to use a
;; `flush!` to robustly detect that demand for its services no longer
;; exists even at startup time.
;;
;; A speculative idea, if we set aside the (in principle) documented
;; requirement that the LLL demand-matcher places on its supply tasks,
;; is to use a kind of contract-monitor to enforce the invariant that
;; demand *cannot* fluctuate too rapidly. One might write that "if
;; (listen 6000) is asserted, then if (listen 6000) is retracted,
;; (observe (listen 6000)) must have been asserted in the causal
;; history of the retraction", but what does "causal history" mean,
;; precisely? And how can it be soundly and efficiently tracked?
;;
;; The only "fix" that solves the problem, is currently implementable,
;; and allows supply tasks to escape responsibility for noticing their
;; own superfluity that I have thought of is to modify the
;; demand-matcher to do something like `during/spawn` is doing, using
;; an auxiliary protocol to centralise tracking of demand and supply
;; at the demand-matcher rather than delegating it to the services.

So, what do we do? Leave demand-matcher alone, and "repair" its clients that don't honour its precondition? Or alter demand-matcher to remove the state-tracking it's doing in favour of something more like the state-tracking implicit in the implementation of during/spawn?