Threads are disabled if an error occurs

When an error is thrown in a threaded loop, only one thread is used in threaded loops thereafter.

julia> function f!(a)
           Threads.@threads for i in eachindex(a)
               a[i] = Threads.threadid()
           end
           a
       end
f! (generic function with 1 method)

julia> function g!(a)
           Threads.@threads for i in eachindex(a)
               sleep(Threads.threadid())
               a[i] = log(-Threads.threadid())
           end
           a
       end
g! (generic function with 1 method)

julia> a = zeros(Threads.nthreads())
6-element Array{Float64,1}:
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0

julia> f!(a)
6-element Array{Float64,1}:
 1.0
 2.0
 3.0
 4.0
 5.0
 6.0

julia> g!(a)
ERROR: TaskFailedException:
DomainError with -1.0:
log will only return a complex result if called with a complex argument. Try log(Complex(x)).
Stacktrace:
 [1] throw_complex_domainerror(::Symbol, ::Float64) at ./math.jl:32
 [2] log(::Float64) at ./special/log.jl:285
 [3] macro expansion at ./special/log.jl:395 [inlined]
 [4] (::var"##19#threadsfor_fun#4"{Array{Float64,1},Base.OneTo{Int64}})(::Bool) at ./threadingconstructs.jl:64
 [5] (::var"##19#threadsfor_fun#4"{Array{Float64,1},Base.OneTo{Int64}})() at ./threadingconstructs.jl:31
Stacktrace:
 [1] wait(::Task) at ./task.jl:251
 [2] macro expansion at ./threadingconstructs.jl:75 [inlined]
 [3] g!(::Array{Float64,1}) at ./REPL[2]:2
 [4] top-level scope at REPL[5]:1

julia> a
6-element Array{Float64,1}:
 1.0
 2.0
 3.0
 4.0
 5.0
 6.0

julia> f!(a)
6-element Array{Float64,1}:
 1.0
 1.0
 1.0
 1.0
 1.0
 1.0

julia> Threads.nthreads()
6

This is on Julia v1.3.0-rc1.0. Julia v1.2.0-rc2.0 behaves similar (only a slightly different error message). I’m using the generic Linux x86_64 binaries.

Is this behaviour expected? How can I enable all threads after such an error without restarting Julia?

This is a bug; it seems to occur because the C code jl_threading_run can throw, but the julia code doesn’t expect it to and omits to reset the variable Threads.in_threaded_loop. Arguably we should remove in_threaded_loop entirely and replace it with a julia implementation based on @spawn, though I’m not sure what the best approach is in the 1.3 timeframe.

If you could submit a bug report issue on github that would be great.

Thanks! I’ve opened an issue (https://github.com/JuliaLang/julia/issues/32970).

1 Like