From 2eee695e92f7f7ef6a9e9e8b9929681850e64cab Mon Sep 17 00:00:00 2001 From: Martin Kavalar Date: Thu, 31 Oct 2024 11:02:51 -0700 Subject: [PATCH] Support interrupting (recursive) function call --- src/sci/impl/fns.cljc | 4 ++++ test/sci/core_test.cljc | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/sci/impl/fns.cljc b/src/sci/impl/fns.cljc index 46403273..cb471c95 100644 --- a/src/sci/impl/fns.cljc +++ b/src/sci/impl/fns.cljc @@ -24,6 +24,8 @@ ~@(when varargs [`(aset ~'invoc-array ~'vararg-idx ~varargs-param)]) (loop [] + #?(:clj (when (java.lang.Thread/.isInterrupted (Thread/currentThread)) + (throw (java.lang.InterruptedException.)))) (let [ret# (types/eval ~'body ~'ctx ~'invoc-array)] (if (kw-identical? :sci.impl.analyzer/recur ret#) (recur) @@ -44,6 +46,8 @@ ~@(when varargs [`(aset ~'invoc-array ~'vararg-idx ~varargs-param)]) (loop [] + #?(:clj (when (java.lang.Thread/.isInterrupted (Thread/currentThread)) + (throw (java.lang.InterruptedException.)))) (let [ret# (types/eval ~'body ~'ctx ~'invoc-array)] (if (kw-identical? :sci.impl.analyzer/recur ret#) (recur) diff --git a/test/sci/core_test.cljc b/test/sci/core_test.cljc index c0d0226e..341a5a1c 100644 --- a/test/sci/core_test.cljc +++ b/test/sci/core_test.cljc @@ -1703,15 +1703,30 @@ (is (true? (sci/eval-string "(exists? js/console.log)" {:classes {'js js/globalThis :allow :all}}))) (is (false? (sci/eval-string "(exists? js/foo.bar)" {:classes {'js js/globalThis - :allow :all}}))) + :allow :all}}))) (is (false? (sci/eval-string "(exists? js/console.log.foobar)" {:classes {'js js/globalThis :allow :all}}))) (is (false? (sci/eval-string "(exists? console.log)" {:classes {'js js/globalThis :allow :all}}))))) +#?(:clj + (deftest interrupt-test + (testing "check that long-running recursive function can be interrupted") + (let [thread (Thread. (fn [] + (time + (sci/eval-form + (sci/init {}) + '((fn a [n] (if (#{0 1} n) 1 (+ (a (- n 2)) (a (- n 1))))) 35)))))] + (.start thread) + (is (= java.lang.Thread$State/RUNNABLE (.getState thread))) + (.interrupt thread) + (Thread/sleep 1) + (is (= java.lang.Thread$State/TERMINATED (.getState thread)))))) + ;;;; Scratch (comment (eval* 1 '(inc *in*)) (test-difference "foo" "[10 10]" 0 10) (test-difference "rand" #(rand) 0 10)) +