Reputation: 1132
What is the best way to propagate errors out from a separate thread (eg. start block, Proc::Async, or sub containing these). Simply wrapping the code that spins off a new thread in a try/CATCH block does not work, and using await only works depending on the return value of the sub routine (ie. a sub returning self will not work with the await approach).
Upvotes: 9
Views: 232
Reputation: 1132
Following the convention used in Go to pass errors out of go routines using channels, I found the same approach to work in Raku. One can use a Channel to send errors out of the asynchronous code to be handled by the main thread.
Example:
my $errors = Channel.new;
my $err-supply = $errors.Supply;
$err-supply.tap(-> $e {say "handle error: $e"});
start {
die "something went horribly wrong";
CATCH {
default {
$errors.send($_);
}
}
}
sleep 1;
Upvotes: 4
Reputation: 23517
Theoretically, that code should die:
As of the 6.d version of the language, start statement prefix used in sink context will automatically attach an exceptions handler. If an exception occurs in the given code, it will be printed and the program will then exit, like if it were thrown without any start statement prefixes involved.
use v6.c;
start { die }; sleep ⅓; say "hello"; # OUTPUT: «hello»
use v6.d;
start { die }; sleep ⅓; say "hello";
# OUTPUT:
# Unhandled exception in code scheduled on thread 4
# Died
# in block at -e line 1
In this case it's a weird situation because you're not sinking the promise (you're returning it), but eventually you sink it because you're running it in void context.
The same documentation gives you the solution: don't sink the context:
# Don't sink it:
my $ = start { die }; sleep ⅓; say "hello"; # OUTPUT: «hello»
# Catch yourself:
start { die; CATCH { default { say "caught" } } };
sleep ⅓;
say "hello";
Since your program does not die, I would say you're in the second situation. For some reason, it's not sunk. But whatever is the situation, the solution is the same: you need to catch the exception inside the same code block.
Solution: await
the promise (which will not sink it) or assign it to some variable, so that the surrounding code dies too. But responding your OP, no, you can't catch an exception from another thread, same way you can't catch an exception from another block.
Upvotes: 5
Reputation: 32404
Use await
.
For example, replace these three lines in your code:
foo;
bar;
baz;
with:
await foo, bar, baz;
Upvotes: 6