Fork me on GitHub
#clojure-dev
<
2019-10-09
>
arohner21:10:30

I have what appears to be a locals-clearing bug when using core.async thread

(let [close? (promise)
      thread-ch (a/go-loop []
                  (when (not (realized? close?))
                    (try
                      (stuff))
                    (recur)))]
  (closeable thread-ch (fn [thread-ch]
                         (deliver close? true)
                         (a/<!! thread-ch))))

arohner21:10:22

this code works. Swapping the go-loop for a/thread reliably causes an NPE when attempting (realized? close?)

arohner21:10:24

println debugging shows close? to be a promise in in the first iteration through the code, and nil in the second

hiredman21:10:50

what version of clojure and core.async? a more minimal repeatable case would be great. I did the minimal to get that to compile with the core.async 0.4.500 and clojure 1.10.1 (basically just defining the free names) and it runs without errors here

hiredman21:10:14

Oh, sorry I misread, that is the passing case, thread is the failing case

hiredman21:10:25

Yep, fails here too

hiredman21:10:16

it would be useful to isolate it without core.async, because thread doesn't do any code transforms so any behavior you get there should be repeatable elsewhere

hiredman21:10:30

oh, I know what it is

hiredman21:10:46

you are replacing go-loop with thread without adding in a loop form

arohner21:10:34

yep, that’s it

hiredman21:10:42

which doesn't error when compiling because the recur just hits the fn introduced by thread, but errors when running because it's a :once fn

arohner21:10:50

(a/thread (loop []…) works

ghadi21:10:55

should :once fns be allowed to recur?

ghadi21:10:33

the function is still being invoked a single time, but has an internal goto to recur

hiredman21:10:23

it seems like they should not, but it seems like the kind of thing someone somewhere is depending on