Open jimrthy opened 7 years ago
Thanks for raising this! You've clearly done a lot more research in this topic than I have. The issue is indeed perplexing, and also not something I haven't run into before; my current usage of with-bindings
in the refresh
task was introduced in response to this same IllegalStateException
you're seeing (or at least a very similar one), and was meant to solve this problem, but I can see now that it has not.
I think your use case is a perfectly reasonable one, and I would certainly expect the library to print an informative error rather than this odd "Can't set!
" business. One thing I could do is add #'*e nil
to that map I pass to with-bindings
, as Karl Mikkelsen suggested. If you can give me a more concrete sequence of steps so I can try to reproduce the issue on my machine (to verify that this would indeed resolve it), I could then release that change as v0.1.1 of this library if it works.
I will try to come up with real repro steps, hopefully this weekend.
(with-bindings {#'*e nil} (boot (refresh))) did not work for me.
Progress report: I tried to update the project where I ran into this originally to get some kind of concrete repro steps.
(boot (refresh)) just fails with this error there, no matter what I try. Even when everything builds fine incrementally, or I restart the JVM and make some completely safe change.
So...curiouser and curiouser.
Could you give a minimal sample project that causes this failure? Perhaps by starting with your existing project and stripping out things that aren't relevant to this bug until getting rid of anything else causes the bug not to occur? It's a bit difficult at the moment for me to try to debug this further, since I don't have a way to reproduce it.
I know, this is the worst kind of bug report.
So, yes. I'm going to try a) stripping it down one step at a time and b) building it back up from the bottom.
There obviously has to be some point in the middle that shows the actual problem.
My root problem was a bad ns declaration.
You can see the problem in test/refreshing_failure/core_test.clj in https://github.com/jimrthy/refreshing-failure. It shows up if you change the ns to core-test instead of refreshing-failure.core-test. It was difficult to track down because both versions compile manually without a complaint.
I can also reproduce the symptom by adding an extra symbol in the middle of a let form, so it has an odd number of args. That one's much more obvious, since it also results in a compiler error.
(sorry this took so long...it's been a busy couple of weeks)
No idea whether it's related, but piggieback just included this release note:
The current nREPL's session's *e binding is now set properly when an uncaught exception occurs.
in
https://github.com/cemerick/piggieback/blob/master/CHANGES.md
Thanks for reminding me of this! I've been quite busy as well, unfortunately, but I'll look into piggieback and your refreshing-failure repo as soon as I can.
Sorry for taking so long to come back to this. I'm trying to reproduce your issue on my end using your refreshing-failure repository, and I'm having a bit of trouble, probably just because I haven't used Emacs or boot-refresh in a while. From the repository root, I execute boot repl -s watch refresh
; then when I change the ns
declaration from
(ns refreshing-failure.core-test
#_core-test
(:require [clojure.test :refer :all]
[refreshing-failure.core :as core]))
to
(ns #_refreshing-failure.core-test
core-test
(:require [clojure.test :refer :all]
[refreshing-failure.core :as core]))
I get this message:
:reloading (core-test)
:error-while-loading core-test
java.lang.Thread.run Thread.java: 748
java.util.concurrent.ThreadPoolExecutor$Worker.run ThreadPoolExecutor.java: 624
java.util.concurrent.ThreadPoolExecutor.runWorker ThreadPoolExecutor.java: 1149
java.util.concurrent.FutureTask.run FutureTask.java: 266
...
clojure.core/binding-conveyor-fn/fn core.clj: 2027
boot.core/boot/fn core.clj: 1029
boot.core/run-tasks core.clj: 1019
boot.task.built-in/fn/fn/fn/fn built_in.clj: 477
boot.task.built-in/fn/fn/fn/fn built_in.clj: 479
boot.task.built-in/fn/fn/fn/fn built_in.clj: 427
boot.task.built-in/fn/fn/fn/fn/fn built_in.clj: 430
boot.task.built-in/fn/fn/fn/fn/fn/fn built_in.clj: 430
samestep.boot-refresh/eval782/fn/fn/fn boot_refresh.clj: 13
...
clojure.core/with-bindings* core.clj: 1970 (repeats 2 times)
clojure.core/apply core.clj: 657
...
samestep.boot-refresh/eval782/fn/fn/fn/fn boot_refresh.clj: 14
...
clojure.tools.namespace.repl/refresh repl.clj: 128
clojure.tools.namespace.repl/refresh repl.clj: 145
clojure.tools.namespace.repl/do-refresh repl.clj: 94
...
clojure.core/alter-var-root core.clj: 5409
clojure.core/alter-var-root core.clj: 5414
...
clojure.tools.namespace.reload/track-reload reload.clj: 52
clojure.tools.namespace.reload/track-reload-one reload.clj: 35
...
clojure.core/require core.clj: 5911 (repeats 2 times)
clojure.core/apply core.clj: 659
...
clojure.core/load-libs core.clj: 5873
clojure.core/load-libs core.clj: 5889
clojure.core/apply core.clj: 659
...
clojure.core/load-lib core.clj: 5832
clojure.core/load-lib core.clj: 5851
clojure.core/load-lib/fn core.clj: 5852
clojure.core/load-one core.clj: 5812
...
clojure.core/load core.clj: 5991
clojure.core/load core.clj: 6007
clojure.core/load/fn core.clj: 6008
...
java.io.FileNotFoundException: Could not locate core_test__init.class or core_test.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name.
Elapsed time: 0.274 sec
This seems different from the "Can't set!
" error you say you're getting; are there different steps I should take to reproduce the issue?
Basic Idea: Trying to run (boot (refresh)) failed without much information.
Expected:
Actual: "java.lang.IllegalStateException: Can't set!: *e from non-binding thread"
Details:
I have my doubts that this is a boot-refresh issue. I can easily see it being a problem in clojure.tools.namespace, boot, or even CIDER or nrepl. Or maybe just that I need to buckle down and learn a refactoring library. But I figured I should start somewhere, asking someone who might have ideas about where to go with it. And...maybe.
I'm using the straight 0.1.0 release in a pretty vanilla project. I've added some dependencies on some logging libraries, clojure 1.9.0-alpha17, and org.clojure/spec.alpha 0.1.123. It's basically a homework assignment.
After a refactoring session, trying to run (boot (refresh)) from CIDER (I'm not sure whether that matters or not) failed with "java.lang.IllegalStateException: Can't set!: *e from non-binding thread"
Doing a google search for that led me to https://stackoverflow.com/questions/43077104/boot-refresh-cant-set-e-from-non-binding-thread.
Digging through the nrepl message buffer didn't reveal anything interesting, except a map of the namespaces that it was trying to refresh.
Going back through those one at a time in dependency order revealed that the actual problem was that I'd moved a function but was still trying reference it directly from the original ns.
The actual problem for me was trivial, since I'm dealing with about half a dozen namespaces. If this had been a bigger project, though...I guess I could have tracked it down by killing my JVM and debugging the errors as I tried to start it back up.
Yuck.
Any thoughts about who we should point this out to?
Thanks, James