I don't get an error messages after a task/ thread failed

Shouldn’t I get notified it a inner task fails?

Yes you should:

julia> t = @async begin
           sleep(1)
           error("FAIL")
       end
Task (runnable) @0x00007f0fd9203820

julia> fetch(t)
ERROR: TaskFailedException:
FAIL
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] macro expansion at ./REPL[1]:3 [inlined]
 [3] (::var"#5#6")() at ./task.jl:333
Stacktrace:
 [1] wait at ./task.jl:251 [inlined]
 [2] fetch(::Task) at ./task.jl:266
 [3] top-level scope at REPL[2]:1
julia> t = Threads.@spawn begin
           sleep(1)
           error("FAIL")
       end
Task (runnable) @0x00007f0fd92004f0

julia> fetch(t)
ERROR: TaskFailedException:
FAIL
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] macro expansion at ./REPL[3]:3 [inlined]
 [3] (::var"#7#8")() at ./threadingconstructs.jl:113
Stacktrace:
 [1] wait at ./task.jl:251 [inlined]
 [2] fetch(::Task) at ./task.jl:266
 [3] top-level scope at REPL[4]:1

Or are we not speaking of the same thing?

1 Like

Thank you for the quick anwser!

julia> Threads.@spawn @async error("Fail")
Task (done) @0x0000000010821fb0

I did this.

You need to fetch the result.

1 Like

Shouldn’t this fire anyway?

I think it should. We need structured concurrency for this:

Until we get structured concurrency, making sure to wrap @async and @spawn always with @sync is the closest thing you can do.

2 Likes

How would I use @sync here?

function t()
    @async error("")
    return 1
end

t()

Either return the task and wait for it or put @sync in t. @sync syncs the tasks that are lexically enclosed.

Treating something like this safely requires so-called nursery (also known as task group and a few other names). ATM, if you want a task to live longer than the function creating it, you need to manually pass it back to the caller. It’s not safe (you may forget doing so). That’s why I think we need structured concurrency.

I think I don’t mind the unstructured concurrency. But it’s very important to have a stacktrace if something fails! Where is the right place to say that?

In what task should the error be thrown?

I think the whole program should stop running unless you started the task in a try-catch-block.

I think the error should be thrown in the most inner task and propagate out until it reaches a try-catch-block or crashes the program.

The stack trace should go from the occurred error through the started task and so on.

These are my first thoughts :slight_smile:

That is structured concurrency.

Would this

function f()
    @async sleep(10)
    return 1
end
try f() |> println catch end
dont_have_to_wait_and_do_the_next_thing()

still work with structured concurrency?

You’d write something like

function f(nursery)
    @async nursery sleep(10)
    return 1
end

try
    withnursery() do nursery
        f(nursery) |> println
        dont_have_to_wait_and_do_the_next_thing()
    end
catch
end

I don’t understand the syntax. What is withnursery() and where is it defined?

The syntax gets more complicated. What’s the point against:

It’s bad because the caller can’t tell if your function or any function that might exist in the call stack starting from your function may leak un-synchronized tasks; i.e., it violates so-called “black box rule”.

For more information, please have a look at Julep https://github.com/JuliaLang/Juleps/blob/master/StructuredConcurrency.md and the discussion in the PR. Your point is related to this discussion on effect system which is effectively a dynamically-scoped nursery: https://github.com/JuliaLang/julia/issues/33248#issuecomment-573365469

1 Like

I’m not sure, what I want. Both sites have their benefits…

This is my solution as far:

macro my_async(ex)
    quote
        @async try $(esc(ex))
        catch e
           println("IN @my_async") 
           # Here I would like to get the definition line number of `ex`
           @show e
        end
    end
end

So now I get feedback if a task fails.

FWIW, you can improve the error printing with

macro my_async(ex)
    quote
        @async try 
            $(esc(ex))
        catch e
            println("In task:") 
            @error(exception = (e, catch_backtrace()))
        end
    end
end
1 Like