[fix] uncaught->error! wasn't working (@benalbrecht)

`__thread` handler arg was being masked by `__thread` in signal implementation,
Ref. https://clojurians.slack.com/archives/C06ALA6EEUA/p1727713025725089
This commit is contained in:
Peter Taoussanis 2024-10-01 11:00:40 +02:00
parent ecf4824f6b
commit 7f52cb1843
2 changed files with 22 additions and 7 deletions

View file

@ -332,17 +332,21 @@
See `uncaught->handler!` and `error!` for details."
{:arglists (impl/signal-arglists :uncaught->error!)}
[& args]
(let [msg-form ["Uncaught Throwable on thread: " `(.getName ~(with-meta '__thread {:tag 'java.lang.Thread}))]
(let [msg-form ["Uncaught Throwable on thread:" `(.getName ~(with-meta '__thread-arg {:tag 'java.lang.Thread}))]
opts
(impl/signal-opts `uncaught->error! (enc/get-source &form &env)
{:kind :error, :level :error, :msg msg-form}
:error :id :dsc (into ['__throwable] args))]
:error :id :dsc (into ['__throwable-arg] args))]
`(uncaught->handler!
(fn [~'__thread ~'__throwable]
(fn [~'__thread-arg ~'__throwable-arg]
(impl/signal! ~opts))))))
(comment (macroexpand '(uncaught->error! ::my-id)))
(comment
(macroexpand '(uncaught->error! ::uncaught))
(do
(uncaught->error! ::uncaught)
(enc/threaded :user (/ 1 0))))
#?(:clj
(defn uncaught->handler!
@ -352,9 +356,10 @@
See also `uncaught->error!`."
[handler]
(Thread/setDefaultUncaughtExceptionHandler
(reify Thread$UncaughtExceptionHandler
(uncaughtException [_ thread throwable]
(handler thread throwable))))
(when handler ; falsey to remove
(reify Thread$UncaughtExceptionHandler
(uncaughtException [_ thread throwable]
(handler thread throwable)))))
nil))
;;;; Interop

View file

@ -671,6 +671,16 @@
(testing "Signals in go macros"
[(async/go (tel/log! "hello"))]))
#?(:clj
(deftest _uncaught->handler!
(let [p (promise)]
[(do (tel/add-handler! ::p (fn ([]) ([sig] (p sig))) {}) :add-handler)
(is (nil? (tel/uncaught->error! ::uncaught)))
(do (enc/threaded :user (throw ex1)) :run-thread)
(is (sm? (deref p 2000 nil) {:kind :error, :level :error, :id ::uncaught, :error ex1}))
(is (nil? (tel/uncaught->error! nil)))
(do (tel/remove-handler! ::p) :remove-handler)])))
;;;; Interop
(comment (def ^org.slf4j.Logger sl (org.slf4j.LoggerFactory/getLogger "my.class")))