Can you find where this asynchronous program get stuck at?

I wrote a weird test function

function test()
    function taskbody(k, x, j, e)
        sleep(0.5 * j)
        println("At k = $k, j = $j, x = $x")
        @lock mylock i+=1
        notify(e)
    end
    my_lock = Threads.ReentrantLock()
    i = 0
    e = Base.Event()
    for k = 1
        x = [-10i, -i, i, 10i] # update!
        t_vec = let e = e
            [@task taskbody(k, x, j, e) for j = 1:7]
        end
        schedule.(t_vec)
        wait(e) # any j can remove this block
        error("Can you reach here?")
    end
end;

You see, I miswrote my_lock as mylock carelessly. But surprisingly I cannot see an ERROR!

julia> Threads.nthreads(:default), Threads.nthreads(:interactive)
(8, 0)

julia> @isdefined mylock
false

julia> # load the definition of `test` above

julia> test()
At k = 1, j = 1, x = [0, 0, 0, 0]
At k = 1, j = 2, x = [0, 0, 0, 0]
At k = 1, j = 3, x = [0, 0, 0, 0]
At k = 1, j = 4, x = [0, 0, 0, 0]
At k = 1, j = 5, x = [0, 0, 0, 0]
At k = 1, j = 6, x = [0, 0, 0, 0]
At k = 1, j = 7, x = [0, 0, 0, 0]
# get stuck at here 

Can you find where the call test() get stuck at?

Oh, I see, it won’t error if you don’t wait for the task.

julia> t = @task error("miswrote");

julia> schedule(t);

julia> 

It’s quite annoying that you won’t see the error until the task is waited for, but there’s nowhere to throw the error.

There’s a similar problem with Channels, which seems to be fixed in 1.12.

1 Like