-
Notifications
You must be signed in to change notification settings - Fork 79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DO NOT MERGE: Prototype some potential error handling ways #192
base: master
Are you sure you want to change the base?
Conversation
@@ -34,25 +34,23 @@ pub enum Method { | |||
pub struct Actor; | |||
impl Actor { | |||
/// Constructor for Account actor | |||
pub fn constructor<BS, RT>(rt: &mut RT, address: Address) -> Result<(), ActorError> | |||
pub fn constructor<BS, RT>(rt: &mut RT, address: Address) -> Result<(), Abort> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that Abort
can't happen, why not just return ()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I wanted to potential for actually returning an error in debug scenarios. My idea was that we could have sth like a debug
feature, where Abort
would collect data and actually be a returned value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One alternative design I had was
fn foo() -> Abort<T> {}
type Abort<T> = Result<T, AbortError>;
to make it even more visual that this is a special kind of exit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I wanted to potential for actually returning an error in debug scenarios. My idea was that we could have sth like a debug feature, where Abort would collect data and actually be a returned value.
Ok, that's reasonable. Although, IMO, we get better information if we abort immediately (and ask wasmtime for a backtrace). See https://docs.wasmtime.dev/api/wasmtime/struct.Config.html#method.wasm_backtrace_details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some scope for divergent behaviour between the two cases here. I guess that this Abort is intended to always be immediately propagated with ?
.
Up at this high level of the actor entry points, I would probably lean towards Steb's initial take that actually aborting is better. We would want a way to shim that call for testing, though, wrapping out the underlying static call so we can use a mock/fake VM instead.
I like the usability, but I also kind of hate it because things that look like they should return an error, actually just fail. How about just adding a panic handler? That way we can add Or add a custom |
The reason I don't want to use |
If we can find a shorter name I would be okay with an explicit call, but I am not fully convinced it is actually better, but I understand your confliction. |
But actually, we can't do that because that's what we're calling async sends in future FVM versions. Decisions have been made. |
I guess we are sticking with |
@@ -34,25 +34,23 @@ pub enum Method { | |||
pub struct Actor; | |||
impl Actor { | |||
/// Constructor for Account actor | |||
pub fn constructor<BS, RT>(rt: &mut RT, address: Address) -> Result<(), ActorError> | |||
pub fn constructor<BS, RT>(rt: &mut RT, address: Address) -> Result<(), Abort> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some scope for divergent behaviour between the two cases here. I guess that this Abort is intended to always be immediately propagated with ?
.
Up at this high level of the actor entry points, I would probably lean towards Steb's initial take that actually aborting is better. We would want a way to shim that call for testing, though, wrapping out the underlying static call so we can use a mock/fake VM instead.
@@ -82,7 +80,7 @@ impl ActorCode for Actor { | |||
let addr = Self::pubkey_address(rt)?; | |||
Ok(RawBytes::serialize(addr)?) | |||
} | |||
None => Err(actor_error!(SysErrInvalidMethod; "Invalid method")), | |||
None => Err(actor_error!(SysErrInvalidMethod; "Invalid method").into()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get this is just prototyping, but I want only one of the ActorError
or Abort
types to survive. They're going after the same problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They definitely should survive both in this construction. The conversion into an Abort
is what triggers the abort, where as ActorError
still can be used inside an actor to communicate recoverable errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think ActorError should be used for recoverable errors. I don't think there are use cases for that. I would say recoverable errors should not specify an abort code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where would that mapping to codes live then?
#[cfg(not(feature = "fil-actor"))] | ||
fn maybe_abort(exit_code: ExitCode, msg: Option<&str>) -> ! { | ||
// TODO: maybe not panic, needs discussion what we want here | ||
panic!("Abort: {}: {:?}", exit_code, msg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works well in Go. If we can reliably catch the panic, e.g. in test harnesses, and inspect the exit code, then this could be good. My read of the Rust docs suggested this was even more frowned upon than in Go, though. cc @ZenGround0
I would make the msg
non-optional.
macro_rules! ensure { | ||
($cond:expr, $code:ident, $msg:literal $(,)?) => { | ||
if !$cond { | ||
return Err($crate::actor_error!($code, $msg).into()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious: why use into
rather than just construct the Abort
explicitly here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it is not possible to construct an Abort
, only be triggering the into
implementation. This does not necessarily convert into an Abort
, it could just convert into itself or other Error types depending on where it is used.
Co-authored-by: Steven Allen <steven@stebalien.com>
9c92adb
to
bf4c523
Compare
(This will be a post M1 task - will be a part of the control flow immediate interruption on error_ epic to match go's behaviour |
Split by commits
Abort
error that callsrt::abort
when converted into, allowing a very explicit triggering via type conversion on the highlevel methods, while still being able to useActorError
in all internal methods without triggering aborts.