Demonstrate the general insufficiency of the approach of commit 2a0197b

This commit is contained in:
Tony Garnock-Jones 2017-08-27 07:50:09 -04:00
parent e0dc583f51
commit 0acd504d05
4 changed files with 86 additions and 6 deletions

View File

@ -6,12 +6,24 @@
;; 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.
;; Another 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.
;; 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.
;;
;; A speculative idea 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 both solves the problem and is currently
;; implementable 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.
(require syndicate/protocol/advertise)
(require/activate syndicate/drivers/tcp)

View File

@ -0,0 +1,45 @@
(#f #f name-summary ((() . "'ground")))
(#f #s(spacetime (meta) 0) actions-produced 1)
(#f #s(spacetime (0) 1) spawn "drivers/tcp:dm:listener")
(#s(spacetime (0) 1) #s(spacetime (0) 2) actions-produced 1)
(#f #s(spacetime (1) 3) spawn "drivers/tcp:dm:connect")
(#s(spacetime (1) 3) #s(spacetime (1) 4) actions-produced 1)
(#f #s(spacetime (2) 5) spawn "strobe")
(#s(spacetime (2) 5) #s(spacetime (2) 6) exit "#f")
(#s(spacetime (2) 5) #s(spacetime (2) 7) actions-produced 2)
(#s(spacetime (meta) 0) #s(spacetime () 8) action-interpreted patch "- ::: nothing\n+ <s:observe/1 <s:outbound/1 ★ {#t}\n+ <s:observe/1 <s:observe/1 <s:inbound/1 ★ {#t}\n")
(#s(spacetime (1) 9) #s(spacetime (1) 10) turn-begin)
(#s(spacetime (1) 10) #s(spacetime (1) 11) turn-end)
(#s(spacetime (0) 12) #s(spacetime (0) 13) turn-begin)
(#s(spacetime (0) 13) #s(spacetime (0) 14) turn-end)
(#f #s(spacetime () 15) turn-end)
(#s(spacetime () 17) #s(spacetime () 18) turn-begin)
(#s(spacetime (0) 2) #s(spacetime () 19) action-interpreted patch "- ::: nothing\n+ <s:observe/1 <s:advertise/1 <s:observe/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 ★ ★ {#t}\n+ <s:observe/1 <s:advertise/1 <s:advertise/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 ★ ★ {#t}\n+ <s:advertise/1 <s:advertise/1 <s:advertise/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 ★ ★ {#t}\n")
(#s(spacetime (1) 4) #s(spacetime () 20) action-interpreted patch "- ::: nothing\n+ <s:observe/1 <s:observe/1 <s:tcp-channel/3 <s:tcp-handle/1 ★ <s:tcp-address/2 ★ ★ ★ {#t}\n+ <s:observe/1 <s:advertise/1 <s:tcp-channel/3 <s:tcp-handle/1 ★ <s:tcp-address/2 ★ ★ ★ {#t}\n+ <s:advertise/1 <s:observe/1 <s:tcp-channel/3 <s:tcp-handle/1 ★ <s:tcp-address/2 ★ ★ ★ {#t}\n")
(#s(spacetime (2) 7) #s(spacetime () 21) action-interpreted patch "- ::: nothing\n+ <s:advertise/1 <s:observe/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 6000 ★ {#t}\n")
(#s(spacetime () 21) #s(spacetime (0) 22) event patch "- ::: nothing\n+ <s:advertise/1 <s:observe/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 6000 ★ {2}\n" #s(spacetime (2) 7) ((2)))
(#s(spacetime (0) 22) #s(spacetime (0) 23) turn-begin)
(#s(spacetime (0) 23) #s(spacetime (0) 24) turn-end)
(#s(spacetime (0) 24) #s(spacetime (0) 25) actions-produced 1)
(#s(spacetime (2) 7) #s(spacetime () 26) action-interpreted patch "- <s:advertise/1 <s:observe/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 6000 ★ {#t}\n+ ::: nothing\n")
(#s(spacetime () 26) #s(spacetime (0) 27) event patch "- <s:advertise/1 <s:observe/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 6000 ★ {2}\n+ ::: nothing\n" #s(spacetime (2) 7) ((2)))
(#s(spacetime (0) 27) #s(spacetime (0) 28) turn-begin)
(#s(spacetime (0) 28) #s(spacetime (0) 29) turn-end)
(#s(spacetime (2) 7) #s(spacetime () 31) quit)
(#s(spacetime (0) 32) #s(spacetime (0) 33) turn-begin)
(#s(spacetime (0) 33) #s(spacetime (0) 34) turn-end)
(#s(spacetime () 18) #s(spacetime () 35) turn-end)
(#s(spacetime () 37) #s(spacetime () 38) turn-begin)
(#s(spacetime (0) 25) #s(spacetime (3) 39) spawn "(drivers/tcp:listen 6000)")
(#s(spacetime (3) 39) #s(spacetime (3) 40) actions-produced 1)
(#s(spacetime (3) 40) #s(spacetime () 42) action-interpreted patch "- ::: nothing\n+ <s:observe/1 <s:inbound/1 <s:tcp-accepted/4 ★ <s:tcp-listener/1 6000 ★ ★ {#t}\n+ <s:observe/1 <s:advertise/1 <s:observe/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 6000 ★ {#t}\n+ <s:advertise/1 <s:advertise/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 6000 ★ {#t}\n")
(#s(spacetime () 42) #s(spacetime (0) 43) event patch "- ::: nothing\n+ <s:advertise/1 <s:advertise/1 <s:tcp-channel/3 ★ <s:tcp-listener/1 6000 ★ {3}\n" #s(spacetime (3) 40) ((3)))
(#s(spacetime (0) 43) #s(spacetime (0) 44) turn-begin)
(#s(spacetime (0) 44) #s(spacetime (0) 45) turn-end)
(#s(spacetime (3) 47) #s(spacetime (3) 48) turn-begin)
(#s(spacetime (3) 48) #s(spacetime (3) 49) turn-end)
(#s(spacetime (0) 50) #s(spacetime (0) 51) turn-begin)
(#s(spacetime (0) 51) #s(spacetime (0) 52) turn-end)
(#s(spacetime () 38) #s(spacetime () 53) turn-end)
(#s(spacetime () 55) #s(spacetime () 56) turn-begin)
(#s(spacetime () 56) #s(spacetime () 57) turn-end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -0,0 +1,23 @@
#lang syndicate/actor
;; Example showing an interesting design flaw (?) (bug?) in the
;; old-school LLL demand-matcher when demand changes too quickly. 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.
;;
;; Demonstrates that the fix in commit 2a0197b isn't in general
;; sufficient.
(require syndicate/protocol/advertise)
(require/activate syndicate/drivers/tcp)
(define X (advertise (observe (tcp-channel ? (tcp-listener 6000) ?))))
(spawn* #:name 'strobe
(assert! X)
(printf "Asserted ~v\n" X)
;; (begin (send! 'dummy)
;; (retract! X)
;; (printf "Retracted ~v\n" X))
(printf "Terminating.\n"))