Here is a very simple example Leiningen project, made with lein new app hanging
, with only two files, project.clj
:
(defproject hanging "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.6.0"]]
:main hanging.core
:aot [hanging.core]
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
and src/hanging/core.clj
:
(ns hanging.core (:gen-class))
(println "1")
(def problematic (future))
(println "2")
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println 3))
When running the project, this is the output (with the prompt freezing, and I have to kill it with C-c):
% lein clean && lein run
Compiling hanging.core
1
2
After commenting out the problematic
Var definition, this is the output (with the JVM closing):
% lein clean && lein run
Compiling hanging.core
1
2
1
2
3
I'm guessing AOT is the culprit here, but can someone explaing what's exactly going on?
I have no problem with the second (commented) version: during AOT the compiler executes all top level forms, and that's why 1 and 2 are seen twice in the output.
But why does adding the var with an empty future inside change that? Does this mean the compiler gets stuck in the AOT phase? Any details and pointers appreciated...
Per suggested answer, I've added (shutdown-agents)
to (-main)
, but it doesn't change the compilation step (it takes about 60s to compile). But, with (shutdown-agents)
the program doesn't hang anymore.