Undefined variable error not reported using multi-threading

Viewed 95

The following code is a simplification of a code of a library I'm working on. The code runs but it does not produces the expected output. The problem turns out to be the use of a wrong variable name (k instead of c) in the function fn. However, no error was not reported.

fn(ch, c) = put!(ch, k)

chnl = Channel{Char}(1) 

function producer(ch,str)
    for c in str
        fn(ch, c)
    end
end

consumer(ch) = for c in ch
                 print(c)
               end

Threads.@spawn producer(chnl, "Hello World!\n")
Threads.@spawn consumer(chnl)
sleep(1)
println("Done")

Detecting this problem took me a while on the original code, because no error was reported. Is there something I could use to detect this type of problem in the future, specially because function fn is suppose to be written by the user?

2 Answers

seems to produce error for me:

julia> Threads.@spawn producer(chnl, "Hello World!\n")
Task (failed) @0x00007fccc68cc160
UndefVarError: k not defined

changing this to:

t1 = Threads.@spawn producer(chnl, "Hello World!\n")
t2 = Threads.@spawn consumer(chnl)
wait(t1)
wait(t2)
println("Done")

running as a script:

akako@ThinkX /tmp> julia test.jl 
ERROR: LoadError: TaskFailedException
Stacktrace:
 [1] wait(t::Task)
   @ Base ./task.jl:322
 [2] top-level scope
   @ /tmp/test.jl:17

    nested task error: UndefVarError: k not defined
    Stacktrace:
     [1] fn(ch::Channel{Char}, c::Char)
       @ Main /tmp/test.jl:1
     [2] producer(ch::Channel{Char}, str::String)
       @ Main /tmp/test.jl:7
     [3] (::var"#1#2")()
       @ Main ./threadingconstructs.jl:169

After digging a little bit more, an alternative solution is to wrap the body of the function producer in a try-catch statement

function producer(ch,str)
    try
        for c in str
            fn(ch, c)
        end
    catch
        for (exc, bt) in Base.catch_stack()
            showerror(stdout, exc, bt)
            println(stdout)
        end
        exit()
    end
end

Resulting in a stack race of the problem:

/tmp> julia problem.jl
UndefVarError: k not defined
Stacktrace:
 [1] fn(ch::Channel{Char}, c::Char)
   @ Main /tmp/problem.jl:1
 [2] producer(ch::Channel{Char}, str::String)
   @ Main /tmp/problem.jl:8
 [3] (::var"#1#2")()
   @ Main ./threadingconstructs.jl:169
Related