I have a simple single threaded Clojure program that creates a temp file for swapping data. When the program exits normally this file is deleted, however when the program is exited via Ctrl+C, Ctrl+D, or Ctrl+Z that bit of code never executes. I need it to execute regardles sof how the program exits. I know that I need to catch that signal (I've done this before in other languages), but I can't seem to figure out how to do it in Clojure.
I don't know if Clojure has wrapped method for that purpose. In java, you can use Runtime.addShutdownHook()
Registers a new virtual-machine shutdown hook.
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
Update
Here is a simple demo
(.addShutdownHook (Runtime/getRuntime) (Thread. (fn [] (println "Shutting down..."))))
user=> ;; Ctrl-C
Shutting down...
Have a look at the deleteOnExit method in the java.io.File:
(import '(java.io File))
(doto (File/createTempFile "foo" nil nil) (.deleteOnExit))
Related
This is piece of code from The Beauty of Clojure I don't understand what alt! is doing here.
(defn listener [f ch]
(let [stop-ch (chan)]
(go-loop []
(alt!
stop-ch ([_] :no-op)
ch ([msg] (f msg)
(recur))))
{:listener ch :stop stop-ch}))
(defn stop-listener [{:keys [stop]}]
(put! stop :stop))
Especially what does second argument to the alt! which is:
ch ([msg] (f msg)
(recur))
does?
And does go-loop mean that after listener function is called it would wait indefinitely to receive values?
The go loop alt! will execute either block depending on which channel has a message.
You’ll notice that the stop-ch does not recur and therefore after receiving a stop, the go loop will end.
If something is received on the listener channel, it is processed by the function f. The recur then takes us back to the start of the go loop, where alt! will wait for further messages on either the listener or the stop channel.
The listener structure created is a map of two channels - put things into listener and they will be f’ed, put anything onto the stop and the listener will stop. This final detail is then abstracted away for the user by the stop-listener fn.
This whole thing is in essence just a simple adaptor between a core.async channel and a function, with clean up logic.
And does go-loop mean that after listener function is called it would wait indefinitely to receive values?
No. Calling listener won’t block the flow of control. The go loop created will “block” until it receives input on one of the channels, however. I’m using quotes because this isn’t a blocked thread - I really recommend you take a look at some of the basic core.async presentations once you’ve had a play at the REPL. Once you can tie the behaviour up to the theory it’s quite straightforward.
When using transducers on channels are the execution of that trasducer blocking the main thread?
For example (chan 1 long-running-trans)
Would this code delay the main thread until the execution is done?
Creating a channel doesn't per-se do anything on the main execution thread, as the transducer will only get into effect once you put things into the channel.
When you do, there are different consequences from a thread occupation point of view, depending on whether you're running over the JVM or on a JS runtime:
JVM
In the following block:
(let [pipe (chan 1 long-running-trans)]
(go
(>! pipe "stuff"))
(go
(let [stuff (<! pipe)]
(println stuff))))
Whatever code appears within the go blocks will be executed within a dedicate threadpool. As such, neither the put nor the get will keep your main thread busy.
If you were to use the blocking version of the channel operators (>!! or <!!), then you are explicitly asking the runtime to perform them on the main thread, and the transducer will hog your main thread any time you put (>!!) an element into the channel.
JS
When you run on a JS engine, you have only one thread of execution and the non-blocking version of the channel operators (>! and <!). Thus, your transducers will indeed affect your main and only thread. Execution would then follow the normal rules of the JS event loop.
I'm trying to implement a carmine worker in a constantly running process.
When launching the following app with lein run myclass.foo, it just starts the worker and stops it right away.
(def my-worker
(car-mq/worker queue-server "my-queue"
{:handler (fn [{:keys [message attempt]}]
(println "Received" message)
{:status :success})
:auto-start false}))
(defn -main []
(car-mq/start my-worker))
My goal is something like that
Launch the foo listener
foo listener runs in foreground and prints everything that gets posted to the queue
Ctrl-c / quit will close the listener
Running it with lein foo was the wrong approach. I edited the entire question to conform with the 'solution' I found.
The main problem was, that I was using lein run myclass.foo to run it. lein trampoline run myclass.foo launches the app's JVM and gets rid of leiningen's, with seems to be exactly what I need. When using trampoline instead of run, the app doesn't exit right away.
Step 2, to close the connection on ctrl-c is a simple shutdown hook
(.addShutdownHook (Runtime/getRuntime) (Thread. #(car-mq/stop my-worker)))
(def queue-agent (agent (clojure.lang.PersistentQueue/EMPTY)))
(send queue-agent conj "some data for the queue")
(println "test output")
If I run this code, after a couple (!) of seconds the console will output test output and then nothing happens (program is not terminating). I've just checked against a couple of sources that all said the send function is asynchronous and should return immediately to the calling thread. So what's wrong with this? Why is it not returning? Is there something wrong with me? Or with my environment?
So you have two issues: long startup time, and the program does not exit.
Startup: Clojure does not do any tree shaking. When you run a Clojure program, you load and bootstrap the compiler, and initialize namespaces, on every run. A couple of seconds sounds about right for a bare bones Clojure program.
Hanging: If you use the agent thread pool, you must run shutdown-agents if you want the program to exit. The vm simply doesn't know it is safe to shut them down.
When I run the following code it basically works how I intend it to, except that it hangs after the future is finished. What am I missing - some kind of "close agents/threads" call? How should I do this?
(def name-to-greet (promise))
(future
(println "Hello," #name-to-greet))
(print "What is your name? ")
(flush)
(deliver name-to-greet (read-line))
Futures use the agent thread pool, which uses non-daemon threads, which means Clojure won't shut down till you call (shutdown-agents). imho, this is bogus (see my comments here) and I've made suggestions that Rich said he would consider post-1.2 around this.