The path was ceremony. Under [flan dev] the daemon already decides where it wants to talk to the program and writes it into FLAN_AGENT_SOCKET, which the C side has always honoured over whatever the source named — so the argument was a value nothing read. Outside the daemon any path will do as long as the program says which one it picked. So [start] becomes a macro over two functions: no argument picks the daemon's socket if there is one and otherwise /tmp/flan-agent-<pid>-<clock>.sock, announced on stderr because a socket nobody can name is a socket nobody can connect to. The explicit form stays for a program that wants a fixed path. Extra arguments are spliced into [start-at] rather than dropped, so the arity refusal is still the checker's, at the call site. And the socket is removed on the way out. The bind stashes the path it bound and registers an atexit; the two paths that leave by _exit — the break loop's [abort] and the orphan handler — unlink it by hand, as the orphan handler already did for its own copy of the path. Nothing else takes it away: under the daemon it sits in a temp directory that is still never removed (FIX.org), and outside there is no daemon at all. test/programs/dev-loop.flan now names no socket, which puts the whole daemon block in test_dev.ml behind the zero-argument form; agent-auto.flan is the standalone half, reached only through the line the program printed, and it pins the second (agent/start) as a no-op and the socket as gone at exit.
29 lines
1.0 KiB
Plaintext
29 lines
1.0 KiB
Plaintext
;;;; The zero-argument (agent/start): a program that names no socket at all.
|
|
;;;;
|
|
;;;; Under [flan dev] it binds where the daemon said, exactly as the explicit
|
|
;;;; form did, and nothing here can tell the difference. Run on its own — which
|
|
;;;; is what test_agent.ml does with it — it picks a path under /tmp and prints
|
|
;;;; it to stderr, and that printed line is the only way anything could connect.
|
|
;;;;
|
|
;;;; The second start is here to be a no-op. It answers 0 like the first, does
|
|
;;;; not bind a second socket, and does not print a second line; a program that
|
|
;;;; got its listener from somewhere else and also asks for one by hand is the
|
|
;;;; case that has to keep working.
|
|
(import agent "vendor:agent")
|
|
|
|
(defvar ticks i64)
|
|
|
|
(defn tick [] i64
|
|
(set ticks (+ ticks 1))
|
|
ticks)
|
|
|
|
(defn main [] i32
|
|
(if (< (agent/start) 0)
|
|
(do (println "cannot listen") 1)
|
|
(do
|
|
(print (agent/start)) (println "")
|
|
(print (tick)) (println "")
|
|
(while (= (agent/wait 100) 0) 0)
|
|
(print (tick)) (println "")
|
|
0)))
|