Feature #5856
closedFeature: Raise any object
Description
Feature: Raise any object
= Proposal
The ability to raise any object that conforms to the protocol of Exception.
= Problem
- The Exception subclass hierarchy is well-established.
- CRuby does not allow any object that behaves as an Exception to be raised, it must be a subclass of Exception.
- 3rd-party code often rescues Exception; e.g. for error recovery, retry and/or logging.
- Users need the ability to raise objects that would not normally be rescued by any code;
e.g.: hard timeouts or custom signal handlers in an application.
= Solution
- ruby/eval.c: Remove make_exception() assertion rb_obj_is_kind_of(mesg, rb_mRaiseable).
= Implementation
- See attached patch or https://github.com/kstephens/ruby/tree/trunk-raise-any
= Example
- See test/ruby/test_raise_any.rb
= See also
Files
Updated by kstephens (Kurt Stephens) almost 13 years ago
- File trunk-raise-any.diff trunk-raise-any.diff added
Attached patch.
Updated by matz (Yukihiro Matsumoto) almost 13 years ago
Hi,
In message "Re: [ruby-core:41950] [ruby-trunk - Feature #5856][Open] Feature: Raise any object"
on Sat, 7 Jan 2012 06:51:53 +0900, Kurt Stephens redmine@ruby-lang.org writes:
|= Problem
|
|* The Exception subclass hierarchy is well-established.
|* CRuby does not allow any object that behaves as an Exception to be raised, it must be a subclass of Exception.
|* 3rd-party code often rescues Exception; e.g. for error recovery, retry and/or logging.
|* Users need the ability to raise objects that would not normally be rescued by any code;
| e.g.: hard timeouts or custom signal handlers in an application.
Are you saying that we should be able to raise exception that can not
(normally) be caught? I don't think it's good practice. For such
purpose, use catch/throw. Or is there any other (preferably concrete)
use-case?
matz.
Updated by nobu (Nobuyoshi Nakada) almost 13 years ago
- Category set to core
- Status changed from Open to Feedback
- Assignee set to matz (Yukihiro Matsumoto)
=begin
- 3rd-party code often rescues (({Exception})); e.g. for error recovery, retry and/or logging.
- Users need the ability to raise objects that would not normally be rescued by ((any)) code;
e.g.: hard timeouts or custom signal handlers in an application.
It doesn't sound to make sense.
Then such 3rd-party code will just rescue (({Object})) (or (({BasicObject}))) instead of (({Exception})), won't it?
What you expect seems something different from exceptions to me.
=end
Updated by matz (Yukihiro Matsumoto) almost 13 years ago
C++ style raising any object does not seem like "exception handling" for me. Besides that, since exception dispatch is based on inheritance hierarchy, it is natural (for me at least) to use Exception as a root of all exceptions.
Updated by kstephens (Kurt Stephens) almost 13 years ago
One can rescue Exception (or Object); this also rescues SystemExit, Interrupt, etc. There is plenty of code out there that rescues Exception but does not rethrow SystemExit and Interrupt; it's a common design mistake. IMO, SystemExit is really a global control flow mechanism, not an exceptional condition; not debating this particular issue.
The issue is 3rd-parties often rescue Exception as a catch-all, to provide fallback, logging, etc; thus it prevents the raising objects that 3rd parties should never rescue accidentally. rescue Object will trap everything and is usually considered bad style. This patch does not prevent it. Rather this patch, prevents 3rd-party code from accidentally rescuing exceptional conditions that they had not designed for.
Examples of exceptional control flows that 3rd-parties should not rescue accidentally via rescue Exception:
- application container management
- controlled termination of runaway worker process
- hard Timeouts, that if incorrectly rescued, prevent a system from behaving according to real-world timing constraints.
Removing the "only Exceptions can be thrown" constraint increases flexibility; it allows objects that quack like an Exception to be thrown.
Exception is effectively a fragile base class, forcefully tied to the run-time; it prevents the use of the exception handling mechanism via duck-typing.
Updated by mame (Yusuke Endoh) almost 12 years ago
- Target version set to 2.6
Updated by matz (Yukihiro Matsumoto) almost 12 years ago
- Status changed from Feedback to Rejected
If we allow raising non Exception object, the library authors will catch Object (or even BasicObject), and this time we will have no work around. So, it's matter of disciplined exception raising/handling. As non-local exit not to be handled, use throw, and as exception handler, do not use Exception.
Matz.