figwheel-main 2025-02-18

I’m running into a (possibly related) issue in which run-tests-async successfully completes all tests but doesn’t terminate. I have a rather clunky workaround (see the thread); if anyone could help me simplify it, that’d be greatly appreciated. Current setup and issue: • My -main function is like this:

(defn -main [& _args]
  (figwheel.main.testing/run-tests-async 10000))
• I run clojure -M -m figwheel.main -m • The console output looks like this:
Ran 2 tests containing 4 assertions.
0 failures, 0 errors.
:figwheel.main.testing/success
• The process doesn’t terminate. Workaround: See the thread below. It’s quite long.

I updated figwheel-main to 0.2.21-SNAPSHOT and am using Firefox for headless tests. Figwheel does terminate properly now. Thanks! Although, I still decided to keep this post-build hook just in case:

(ns post-build-hooks
  (:require [figwheel.repl]))

(defn ensure-system-exit [_]
  (alter-var-root #'figwheel.repl/tear-down-everything-but-server
    (fn [f]
      (fn new-f [repl-env]
        (f repl-env)
        (when-not (:prevent-server-tear-down repl-env)
          (future
            (Thread/sleep 5000)
            (shutdown-agents)
            (System/exit 0)))))))

Wait, are you sure that tear-down-everything-but-server is being called?

yep it is 🙂

Hmmm if the tests print then that probably means that something isn't shutting down? I think the problem is that I'm using a future in figwheel-repl in my last SNAPSHOT deploy. I recently made a commit that cleans up thread usage. I'm going to deploy a new SNAPSHOT with those changes.

If that doesn't work then something else is still running. An easier change that you can test out is if you put a (System/exit) here in the finally clause. https://github.com/bhauman/figwheel-main/blob/master/src/figwheel/main.cljc#L2139

I forgot to mention that I’ve been using version 0.2.20. I tried putting (System/exit 0) in the finally clause, and the process did indeed terminate, albeit with an incorrect exit code (always 0 even if some tests failed). For now I’m putting the custom add-listener code in :post-build-hooks. This way I can continue to use version 0.2.20 from Maven.

Also, when I added (println "Tear-down finished.") at the end of the finally clause in figwheel.main/default-main (https://github.com/bhauman/figwheel-main/blob/30eeec058f5c9ff251c733dd2b2b849c08acf37b/src/figwheel/main.cljc#L2141), the print went through. (This was with all other modifications removed.) I think this confirms that figwheel.main/default-main returns normally and therefore isn’t the cause.

But if you test the 0.2.21-SNAPSHOT and it see if it works I can release it soon.

BC I think that this is fixed. BTW the snapshot is in maven

hmmm I guess I'll have to look into this further

Workaround: I clone figwheel-main and use it as a local dependency. My idea is to explicitly trigger a System/exit call on test success. Here are the changes: • figwheel.main.system-exit:

#?(:cljs
   (defn delayed-system-exit [{:keys [status delay-ms] :as value}]
     (let [msg {:figwheel-event "delayed-system-exit"
                :value value}]
       (figwheel.repl/debug [:delayed-system-exit (pr-str msg)])
       (figwheel.repl/respond-to-connection msg)))
   :clj
   (defn setup []
     (figwheel.repl/add-listener
      ::delayed-system-exit
      (fn [{:keys [response] :as msg}]
        (when (= "delayed-system-exit" (:figwheel-event response))
          (let [status (get-in response [:value :status] 0)
                status (if (integer? status) status 0)
                delay-ms (get-in response [:value :delay-ms] 0)
                delay-ms (if (integer? delay-ms) delay-ms 0)]
            (future
              (Thread/sleep delay-ms)
              (shutdown-agents)
              (System/exit status))))))))
figwheel.main (line 2110):
(let [stolen-repl-env (promise)
                      result-prom (promise)]
                  (async-result/listen result-prom)
                  ;; Explicitly set up `system-exit`.
                  (system-exit/setup)
• My own test namespace:
(defmethod cljs.test/report [:cljs.test/default :end-run-tests] [test-data]
  (if (cljs.test/successful? test-data)
    (do
      (figwheel.main.system-exit/exit-with-status-delay {:status 0 :delay 5000})
      ;; The connection is still alive at this point.
      (figwheel.main.async-result/send "Tests passed!")
      ;; I think Figwheel closes the connection immediately after the `send`.
      )
    (figwheel.main.async-result/throw-ex (ex-info "Tests failed." test-data))))

(defn -main [& _args]
  (figwheel.main.testing/run-tests-async 10000))