Threaded function hanging when run through include, but not through REPL

I have the following code:

const vec = rand(10000)
const shouldrun = Ref(true)

uselessalgo(vec) = vec .= rand(10000)

function uselessLoop(vec, shouldrun)
    while shouldrun[]
        uselessalgo(vec)
        GC.safepoint()
    end
end

function spawnUselessLoop(vec, shouldrun)
    println("Starting loop...")
    shouldrun[] = true
    println("Spawning thread...")
    Threads.@spawn uselessLoop(vec, shouldrun)
    println("Sleeping")
    sleep(1)
    println("Stopping loop...")
    shouldrun[] = false
end

spawnUselessLoop(vec, shouldrun)

If I save this as a file and run it through include("filename"), then it will almost certainly hang for me. First of all, Iā€™m not sure exactly why, I thought GC.safepoint() should prevent this. Can anybody explain this to me?
Then, if I first comment out the function call, and manually call it by typing it in in the REPL, it will almost never hang for me. Why does there seem to be a difference?

It apparently hangs in the interface to libuv (which handles simple IO and the sleep timer), so congratulations on finding a bug in Base concurrency. There seems to be a race between @spawn and some lock used by the interface. Care to file an issue?

The problem appears to go away if one adds an interactive thread (in v1.9), or interposes some computations before the call to println just after @spawn.

Incidentally, the safepoint call is not helpful here since rand allocates.

1 Like