the fact that Exceptions occurring in Tasks are not propagated back to the main thread makes debugging difficult.
at the REPL:
julia> throw(Exception)
ERROR: Exception # printed in red
julia> @async throw(Exception)
Task (failed) @0x00007f6654996680 # in black
on the unix command line:
$ julia -e 'throw(Exception)'
ERROR: Exception
in process_options at ./client.jl:295
in _start at ./client.jl:413
$ echo $?
1
$ julia -e '@async throw(Exception)'
$ echo $?
0
Duplicate of #7626.
This is not too different from other debugging scenarios, where for example results of intermediate computations are not printed by default.
I don't really see how it could work to propagate exceptions from all tasks by default. That would mean blocking calls in the main task could be constantly interrupted by other task failures. For example a read call in the main task would throw an exception not because the read failed, but because some other task failed. It seems very difficult to program in the face of that.
Perhaps errors in background tasks should still be printed to STDERR?
Maybe we should do that in isinteractive mode. But there is a potential problem with getting lots of spurious output from internal things like IJulia, the REPL, or multi.jl. Then you need some kind of "don't print" switch.
Wouldn't the "don't print" switch be to actually wait for the error and ignore it?
I've typically felt that the don't print switch should be the absence of a print statement, but this sounds worth trying. I can see the argument that you want to be encouraged to explicitly handle task failures, either by wrapping certain tasks in try/catch, or by waiting for them elsewhere.
This is a little different than a don't print switch since these are errors, which one does want to default to showing. So yeah, let's try it.
ahah, i didn't know one could capture the exception with wait. would be worth documenting, or did i miss it?
nevertheless, i guess i feel that if anything throws an error, be it the main thread or a task, and that error is not explicitly caught, then it should be printed to STDERR with a backtrace, the whole program should come to a grinding halt, and an error state should be returned. does that not make sense?
Printing the error yes, but many people would probably want it logged and for the program to keep running if possible. Anyway that's more of a detail.
I'm surprised to see the help for wait doesn't mention exceptions. I'll fix that.
Silent failures are just a drain on debugging productivity. My vote is to print any uncaught errors to STDERR. Should be done whether interactive or not. Spurious uncaught errors in IJulia, the REPL, or multi.jl should be fixed over time.
@vtjnash pointed out to me that there is kind of a timing bug here. For example
t = @schedule stuff
# ... do a bunch of I/O ...
wait(t)
If t happens to fail before we hit the wait, the error will be printed, otherwise it won't. Either way the exception will propagate to the wait, but the unpredictable printing is a nuisance. One proposal is to involve the GC, so the error is only printed if the task is unreferenced. Of course, the existence of references, and whether the GC has run, are also fairly subtle and unpredictable matters. Anyway this refreshed my memory about why I've resisted this feature in the past.
One option could be to print the error only when the task object is gc'ed . wait will clear the exception in the task object.
Most helpful comment
Silent failures are just a drain on debugging productivity. My vote is to print any uncaught errors to STDERR. Should be done whether interactive or not. Spurious uncaught errors in IJulia, the REPL, or multi.jl should be fixed over time.