From 86f246dbdb270f6c50d48c2c977ebb425a03195c Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Tue, 27 Dec 2016 01:32:01 -0500 Subject: [PATCH] just might work. close() mapped out. Starting to draw a distinction between clean-close and abrupt-halt. At least, if we're in the connected state, wormhole.close() should take its time and free up server-side resources (nameplate/mailbox) right away, rather than relying on GC/timeouts to release them. It might be useful to make separate "clean" wormhole.close() and "abrupt" wormhole.halt() API calls, except that really when would you ever call halt? To be realistic, only one of two things will happen: * connection happens normally, app finishes, calls "clean" close() * app terminates suddenly, via exception or SIGINT The problem with defining .close() is that I have to make it work sensibly from any state, not just the one plausible "connected" state. Providing .halt() requires defining its behavior from everywhere else. --- docs/w.dot | 10 +++++--- docs/w2.dot | 69 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 53 insertions(+), 26 deletions(-) diff --git a/docs/w.dot b/docs/w.dot index 37e71e4..db5c49b 100644 --- a/docs/w.dot +++ b/docs/w.dot @@ -201,18 +201,22 @@ digraph { C_start [label="Connection\nMachine" style="dotted"] C_start -> C_S_connecting [label="C_start()"] C_S_connecting [label="connecting"] - C_S_connecting -> C_S_connected [label="connected"] + C_S_connecting -> C_P_connected [label="onConnect"] + C_P_connected [shape="box" label="M_connected()"] + C_P_connected -> C_S_connected C_S_connecting -> C_P_stop_connecting [label="C_stop()"] C_P_stop_connecting [shape="box" label="cancel\nconnection\nattempt"] C_P_stop_connecting -> C_S_stopped C_S_connected [label="connected" color="green"] - C_S_connected -> C_S_waiting [label="lost"] + C_S_connected -> C_P_lost [label="onClose"] + C_P_lost [shape="box" label="M_lost()\nstart timer"] + C_P_lost -> C_S_waiting C_S_waiting [label="waiting"] C_S_waiting -> C_S_connecting [label="expire"] C_S_waiting -> C_S_stopped [label="C_stop()"] C_S_connected -> C_S_stopping [label="C_stop()"] C_S_stopping [label="stopping"] - C_S_stopping -> C_S_stopped [label="stopped"] + C_S_stopping -> C_S_stopped [label="onClose"] C_S_stopped [label="stopped"] } diff --git a/docs/w2.dot b/docs/w2.dot index b9aa9c2..1e85c3b 100644 --- a/docs/w2.dot +++ b/docs/w2.dot @@ -14,8 +14,8 @@ digraph { {rank=same; M_S1 M_S1B} M_S1 [label="1: know nothing"] M_S1B [label="1: know nothing\n(bound)"] - M_S1 -> M_S1B [label="connect()"] - M_S1B -> M_S1 [label="lose()"] + M_S1 -> M_S1B [label="M_connected()"] + M_S1B -> M_S1 [label="M_lost()"] M_S1 -> M_S2 [label="M_set_nameplate()"] M_S1B -> M_P_claim1 [label="M_set_nameplate()"] @@ -25,8 +25,8 @@ digraph { {rank=same; M_S2 M_S2B M_P_claim2} M_S2 [label="2: know nameplate\nwant claim\nunknown mailbox\nwant open"] M_S2B [label="2: know nameplate\nwant claim\nunknown mailbox\nwant open\n(bound)"] - M_S2 -> M_P_claim2 [label="connect()"] - M_S2B -> M_S2 [label="lose()"] + M_S2 -> M_P_claim2 [label="M_connected()"] + M_S2B -> M_S2 [label="M_lost()"] M_P_claim2 [shape="box" label="tx claim()"] M_P_claim2 -> M_S2B M_S2 -> M_P2_queue [label="M_send(msg)" style="dotted"] @@ -44,9 +44,9 @@ digraph { {rank=same; M_S3 M_S3B M_P3_open M_P3_send} M_S3 [label="3: claimed\nknown mailbox\nwant open"] M_S3B [label="3: claimed\nknown mailbox\nwant open\n(bound)"] - M_S3 -> M_P3_open [label="connect()"] - M_S3B -> M_S3 [label="lose()"] - /*M_S3B -> M_S2 [label="lose()"]*/ /* not worth it */ + M_S3 -> M_P3_open [label="M_connected()"] + M_S3B -> M_S3 [label="M_lost()"] + /*M_S3B -> M_S2 [label="M_lost()"]*/ /* not worth it */ M_P3_open [shape="box" label="tx open()\ntx add(queued)"] M_P3_open -> M_S3B M_S3B -> M_S3B [label="rx_claimed()"] @@ -63,8 +63,15 @@ digraph { M_P3_process_ours -> M_S3B M_S3B -> M_P3_process_theirs [label="rx_message(side!=me)"] M_P3_process_theirs [shape="box" label="tx release()\nprocess message"] + /* pay attention to the race here: this process_message() will + deliver msg_pake to the WormholeMachine, which will compute_key() and + M_send(version), and we're inbetween M_S2 (where M_send gets queued) + and M_S3 (where M_send gets sent and queued), and we're no longer + passing through the M_P3_open phase (which drains the queue). So + there's a real possibility of the outbound msg_version getting + dropped on the floor, or put in a queue but never delivered. */ M_P3_process_theirs -> M_S4B - M_S3B -> M_P3_close [label="M_close()"] + M_S3B -> M_P3_close [label="M_close(mood)"] M_P3_close [shape="box" label="tx release()\n"] M_P3_close -> M_P_close @@ -72,12 +79,12 @@ digraph { M_S4 [label="4: released\nunwant nameplate\nwant mailbox\nopen\n"] M_S4B [label="4: released\nunwant nameplate\nwant mailbox\nopen\n(bound)"] - M_S4 -> M_P4_release [label="connect()"] + M_S4 -> M_P4_release [label="M_connected()"] /* it is currently an error to release a nameplate you aren't currently claiming, so release() is not idempotent. #118 fixes that */ M_P4_release [shape="box" label="tx open()\ntx add(queued)\ntx release()"] /*M_S4B -> M_S4B [label="rx_claimed() *#118"]*/ - M_S4B -> M_P_close [label="M_close()"] + M_S4B -> M_P_close [label="M_close(mood)"] M_S4B -> M_P4_send [label="M_send(msg)"] M_P4_send [shape="box" label="queue\ntx add(msg)"] M_P4_send -> M_S4B @@ -86,8 +93,8 @@ digraph { M_P4_queue -> M_S4 [style="dotted"] M_P4_release -> M_S4B - M_S4B -> M_S4 [label="lose()"] - /*M_S4B -> M_S2 [label="lose()"]*/ + M_S4B -> M_S4 [label="M_lost()"] + /*M_S4B -> M_S2 [label="M_lost()"]*/ M_S4B -> M_P4_process [label="rx_message()"] M_P4_process [shape="box" label="process message"] M_P4_process -> M_S4B @@ -96,14 +103,16 @@ digraph { M_S4B -> M_S5B [label="rx_released()"] seed [label="from Seed?"] + M_S3 -> seed [style="invis"] + M_S4 -> seed [style="invis"] seed -> M_S5 {rank=same; seed M_S5 M_S5B M_P5_open M_P5_process} M_S5 [label="5: released\nunwant nameplate\nwant mailbox\nopen\n"] M_S5B [label="5: released\nunwant nameplate\nwant mailbox\nopen\n(bound)" color="green"] - M_S5 -> M_P5_open [label="connect()"] + M_S5 -> M_P5_open [label="M_connected()"] M_P5_open [shape="box" label="tx open()\ntx add(queued)"] M_P5_open -> M_S5B - M_S5B -> M_S5 [label="lose()"] + M_S5B -> M_S5 [label="M_lost()"] M_S5B -> M_P5_process [label="rx_message()"] M_P5_process [shape="box" label="process message"] M_P5_process -> M_S5B @@ -114,26 +123,40 @@ digraph { M_P5_queue [shape="box" label="queue" style="dotted"] M_P5_queue -> M_S5 [style="dotted"] - M_S5 -> M_S6 [label="M_close()"] - /*M_S5 -> M_P7_drop [label="M_close()"]*/ - M_S5B -> M_P_close [label="M_close()"] - M_P_close [shape="box" label="tx close()"] + M_S5 -> M_S6 [style="invis"] + M_S5B -> M_P_close [label="M_close(mood)"] + M_P_close [shape="box" label="tx close(mood)"] M_P_close -> M_S6B {rank=same; M_S6 M_P6_close M_S6B} M_S6 [label="6: closing\nunwant mailbox\nopen\n"] M_S6B [label="6: closing\nunwant mailbox\nopen\n(bound)"] - M_S6 -> M_P6_close [label="connect()"] + M_S6 -> M_P6_close [label="M_connected()"] M_P6_close [shape="box" label="tx close()"] M_P6_close -> M_S6B - M_S6B -> M_S6 [label="lose()"] + M_S6B -> M_S6 [label="M_lost()"] M_S6B -> M_S6B [label="rx_released()"] M_S6B -> M_S6B [label="M_close()"] M_S6B -> M_S6B [label="M_send()"] M_S6 -> M_S6 [label="M_send()"] M_S6 -> M_S7 [label="(none)" style="invis"] - /*M_S6 -> M_P7_drop [label="M_close()"]*/ + {rank=same; M_other_closes M_P7_drop} + M_other_closes [label="all\nother\nunbound\nstates" style="dotted"] + M_other_closes -> M_P7_stop [label="M_close()" style="dotted"] + M_P7_stop [shape="box" label="C_stop()"] + M_P7_stop -> M_S7 + /*M_S1 -> M_other_closes [label="M_close()"] + M_S2 -> M_other_closes [label="M_close()"] + M_S3 -> M_other_closes [label="M_close()"] + M_S4 -> M_other_closes [label="M_close()"]*/ + M_S5 -> M_other_closes [style="dotted"] + /*M_S6 -> M_P7_stop [label="M_close()"]*/ + M_S6 -> M_other_closes [style="dotted"] + M_S1B -> M_P7_drop [label="M_close()"] + M_S2B -> M_P2_drop [label="M_close()"] + M_P2_drop [shape="box" label="tx release()"] + M_P2_drop -> M_P7_drop M_S6B -> M_P7_drop [label="rx_closed()"] M_P7_drop [shape="box" label="C_stop()"] M_P7_drop -> M_S7B @@ -141,8 +164,8 @@ digraph { {rank=same; M_S7 M_S7B} M_S7 [label="7: closed\n"] M_S7B [label="7: closed\n(bound)"] - M_S7 -> M_S7B [label="connect()" style="invis"] - M_S7B -> M_S7 [label="lose()"] + M_S7 -> M_S7B [style="invis"] + M_S7B -> M_S7 [label="M_lost()"] M_S7B -> M_S7B [label="M_close()"] M_S7B -> M_S7B [label="M_send()"]