Project

General

Profile

Actions

Feature #21359

open

Updated by Eregon (Benoit Daloze) 29 days ago

Do you have real-world examples where you would use this, e.g. in gems?

Updated by ioquatix (Samuel Williams) 29 days ago

Yes, in Async, I want to set the cause of an exception before raising it later on a fiber.

Additionally, serialisation and deserialisation of exceptions is almost impossible without being able to set the cause, e.g. any kind of Ruby RPC.

Updated by Eregon (Benoit Daloze) 29 days ago

  • Related to : Inconsistent Support for `Exception#cause` in `Fiber#raise` and `Thread#raise` added

Updated by Eregon (Benoit Daloze) 29 days ago

ioquatix (Samuel Williams) wrote in #note-2:

Yes, in Async, I want to set the cause of an exception before raising it later on a fiber.

would be enough for that, although you'd need to wrap the exception + cause-to-be in some extra object.

Additionally, serialisation and deserialisation of exceptions is almost impossible without being able to set the cause, e.g. any kind of Ruby RPC.

WDYM by almost impossible?
Causes can't be cyclic so that's not an issue (which BTW means we would need to check that in this assignment method).
Marshal can do it I guess.
And if not raise self, cause: value + rescue but I agree that's hacky and inefficient.

Serializing exceptions properly without Marshal is probably quite hard yes, not only about the cause but also the internal backtrace representation, the backtrace_locations objects, other internal state for core exceptions that can't always be set in constructor, etc.
But is there a need for that?

Updated by ioquatix (Samuel Williams) 29 days ago

Serializing exceptions properly without Marshal is probably quite hard yes, not only about the cause but also the internal backtrace representation, the backtrace_locations objects, other internal state for core exceptions that can't always be set in constructor, etc. But is there a need for that?

Yes, serialisation with msgpack is painful and impossible to do correctly in some situations, if you have custom serialisation rules for certain object types (using a msgpack factory), you can't use Marshal.dump as part of msgpack's serialisation because it won't correctly serialise the internal objects of the exception.

Updated by Eregon (Benoit Daloze) 28 days ago

msgpack doesn't seem to handle recursive data structures:

irb(main):003> a=[]
=> []
irb(main):004> a<<a
=> [[...]]
irb(main):005> a
=> [[...]]
irb(main):006> a.to_msgpack
msgpack-1.8.0/lib/msgpack.rb:41:in `write': stack level too deep (SystemStackError)

So I think it's unrealistic to try to serialize/deserialize exceptions or complex objects with msgpack, it seems really meant for non-recursive simple data.

Updated by zzak (zzak _) 24 days ago

Another thing to consider is we don't have Exception#backtrace= but instead Exception#set_backtrace.

So an alternative is Exception#set_cause or Exception#set_backtrace(cause:). I guess.

Updated by hsbt (Hiroshi SHIBATA) 24 days ago

  • Status changed from Open to Assigned

Updated by matz (Yukihiro Matsumoto) 15 days ago

I am basically against cause= (or set_cause that is). It makes exceptions more complex. Is it impossible to defer exception creation til it is absolutely needed?

Matz.

Updated by Eregon (Benoit Daloze) 15 days ago

Maybe Exception.new("message", cause: cause) should be supported, but I suppose that might be quite hard to support for all subclasses of Exception.
That's probably the reason it's on raise and not in exception constructor.
BTW it's also raise that sets the (initial) backtrace of an exception, not the exception constructor (unlike in Java).

Maybe Exception#exception could accept a cause: kwarg?

Actions

Also available in: Atom PDF

Like1
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0