# Closure bug (#15276) hits again with multi-threading, but why?!

**URL:** <https://discourse.julialang.org/t/closure-bug-15276-hits-again-with-multi-threading-but-why/21082>\
**Category:** Performance\
**Created:** [February 22, 2019, 2:29pm UTC](https://discourse.julialang.org/t/closure-bug-15276-hits-again-with-multi-threading-but-why/21082 "2019-02-22T14:29:26Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![raminammour](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raminammour/32/13572_2.png) [@raminammour](https://discourse.julialang.org/u/raminammour)\
**Post date:** [February 22, 2019, 2:29pm UTC](https://discourse.julialang.org/t/closure-bug-15276-hits-again-with-multi-threading-but-why/21082/1 "2019-02-22T14:29:26Z")

</div>

Hello,

Below is a MWE of what I am seeing in an application:

```julia
function foo(v)
    #uncomment for Box
    size(v) == (10,10) && error()
    ss=zeros(Float64,Threads.nthreads())
    
    #this does not lead to Box
    #size(v) == (10,10) && error()
    
    Threads.@threads for i2 in 1:size(v,2)
        @simd for i1 in 1:size(v,1)
            tid=Threads.threadid()
            @inbounds ss[tid]+=v[i1,i2]
        end
    end
    return sum(ss)
end

@code_warntype foo(rand(100,100))Body::Any
│╻ Type3 1 ── %1 = %new(Core.Box)::Core.Box
│╻ size │ %2 = (Base.arraysize)(v, 1)::Int64
││ │ %3 = (Base.arraysize)(v, 2)::Int64
││╻╷ _eq │ %4 = (%2 === 10)::Bool
││╻ _eq │ %5 = (%4 === false)::Bool
│││ └─── goto #3 if not %5
│││ 2 ── goto #7
│││╻╷ _eq 3 ── %8 = (%3 === 10)::Bool
│││╻ _eq │ %9 = (%8 === false)::Bool
││││ └─── goto #5 if not %9
││││ 4 ── goto #6
││││ 5 ── goto #6
│││ 6 ┄─ %13 = φ (#4 => false, #5 => true)::Bool
│││ └─── goto #7
││ 7 ┄─ %15 = φ (#2 => false, #6 => %13)::Bool
││ └─── goto #8
│ 8 ── goto #10 if not %15
│ 9 ── invoke Main.error()
│ └─── $(Expr(:unreachable))
│╻ nthreads4 10 ┄ %20 = (Base.Threads.cglobal)(:jl_n_threads, Base.Threads.Cint)::Ptr{Int32}
││╻ unsafe_load │ %21 = (Base.pointerref)(%20, 1, 1)::Int32
│││╻ toInt64 │ %22 = (Core.sext_int)(Core.Int64, %21)::Int64
││╻╷╷ zeros │ %23 = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Float64,1}, svec(Any, Int64), :(:ccall), 2, Array{Float64,1}, :(%22), :(%22)))::Array{Float64,1}
│││ │ %24 = invoke Base.fill!(%23::Array{Float64,1}, 0.0::Float64)::Array{Float64,1}
│ │ (Core.setfield!)(%1, :contents, %24)
│╻╷ macro expansion9 │ %26 = (Base.arraysize)(v, 2)::Int64
││╻╷╷╷ Colon │ %27 = (Base.sle_int)(1, %26)::Bool
│││╻ Type │ (Base.sub_int)(%26, 1)
││││┃ unitrange_last │ %29 = (Base.ifelse)(%27, %26, 0)::Int64
││││ │ %30 = %new(UnitRange{Int64}, 1, %29)::UnitRange{Int64}
│╻ macro expansion │ %31 = %new(getfield(Main, Symbol("##1134#threadsfor_fun#280")){Array{Float64,2},UnitRange{Int64}}, v, %1, %30)::getfield(Main, Symbol("##1134#threadsfor_fun#280")){Array{Float64,2},UnitRange{Int64}}
││╻ threadid │ %32 = $(Expr(:foreigncall, :(:jl_threadid), Int16, svec(), :(:ccall), 0))::Int16
│││╻ + │ %33 = (Base.sext_int)(Int64, %32)::Int64
│││╻ + │ %34 = π (1, Int64)
││││╻ + │ %35 = (Base.add_int)(%33, %34)::Int64
│││╻ == │ %36 = (%35 === 1)::Bool
│││╻ ! │ %37 = (Base.not_int)(%36)::Bool
││ └─── goto #12 if not %37
││ 11 ─ goto #13
││ 12 ─ %40 = Base.Threads.in_threaded_loop::Core.Compiler.Const(Base.RefValue{Bool}(false), false)
│││╻ getproperty └─── %41 = (Base.getfield)(%40, :x)::Bool
││ 13 ┄ %42 = φ (#11 => %37, #12 => %41)::Bool
││ └─── goto #15 if not %42
││ 14 ─ invoke %31(true::Bool)
││ └─── goto #16
││ 15 ─ %46 = Base.Threads.in_threaded_loop::Core.Compiler.Const(Base.RefValue{Bool}(false), false)
│││╻ setproperty! │ (Base.setfield!)(%46, :x, true)
│╻ macro expansion │ $(Expr(:foreigncall, :(:jl_threading_run), Ref{Nothing}, svec(Any), :(:ccall), 1, :(%31), getfield(Main, Symbol("##1134#threadsfor_fun#280")){Array{Float64,2},UnitRange{Int64}}, :(v), :(%1)))
││ │ %49 = Base.Threads.in_threaded_loop::Core.Compiler.Const(Base.RefValue{Bool}(false), false)
││╻ setindex! └─── (Base.setfield!)(%49, :x, false)
│╻ macro expansion 16 ┄ %51 = (Core.isdefined)(%1, :contents)::Bool
││ └─── goto #18 if not %51
││ 17 ─ goto #19
││ 18 ─ $(Expr(:throw_undef_if_not, :ss, false))
││ 19 ┄ %55 = (Core.getfield)(%1, :contents)::Any
││ │ %56 = (Main.sum)(%55)::Any
││ └─── return %56
│ 20 ─ goto #10

```

I understand that this is [15276](https://github.com/JuliaLang/julia/issues/15276), but why is the error check before `ss` causing it (checking after does not). I appreciate any help understanding this so I can catch it in the future (and other users may too).

Thanks!

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [February 22, 2019, 9:18pm UTC](https://discourse.julialang.org/t/closure-bug-15276-hits-again-with-multi-threading-but-why/21082/2 "2019-02-22T21:18:12Z")

</div>

Consider KissThreading.jl if it fits your use case. 15276 has been properly fought under the hood.
