Gracefully exit a Clojure core.async go loop on kill
clojure, core.async, java, signals
Solution
`go` function returns a channel. You may want to `(close! chan)` in shutdown hook.
If you run `lein run` you need a main function that will call `(run)` to start go thread.
(ns async-demo.core
(:require [clojure.core.async :as async
:refer [<! >! <!! timeout chan alt! go close!]]))
(def ch (atom nil))
(defn run []
(go (while true
(<! (timeout 500))
(prn "inside go"))))
(defn -main [& args]
(println "Starting")
(reset! ch (run))
(.addShutdownHook (Runtime/getRuntime)
(Thread. #(do
(println "SHUTDOWN")
(close! @ch))))
(while true
(<!! @ch)))
Problem
I have a top-level core.async go loop. I want it to run indefinitely, at least until I signal it to stop with CTRL-C or kill or similar. I'm currently using java.lang.Runtime/addShutdownHook like this: ``` (ns async-demo.core (:require [clojure.core.async :as async :refer [<! >! <!! timeout chan alt! go]])) (defn run [] (go (loop [] (recur)))) (.addShutdownHook (Runtime/getRuntime) (Thread. #(println "SHUTDOWN"))) ``` Here are my problems: If I start the REPL and `(run)` then it starts and runs in a background thread. When I exit the REPL, I don't see the desired shutdown message. However, when I run from `lein run`, the go loop exits immediately and displays "SHUTDOWN". Neither is what I want. I don't necessarily expect to find a solution that works for all JVM's. I develop on a Mac and deploy to Ubuntu, so I'd like to find a solution that works for both: Mac JVM: java version "1.7.0_45" Java(TM) SE Runtime Environment (build 1.7.0_45-b18) Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode) Ubuntu JVM: java version "1.7.0_25" OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.12.04.2) OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)