820. current_exception()'s interaction with throwing copy ctors

Section: 21.8.6 [propagation] Status: CD1 Submitter: Stephan T. Lavavej Opened: 2008-03-26 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [propagation].

View all issues with CD1 status.

Discussion:

As of N2521, the Working Paper appears to be silent about what current_exception() should do if it tries to copy the currently handled exception and its copy constructor throws. 21.8.6 [propagation]/7 says "If the function needs to allocate memory and the attempt fails, it returns an exception_ptr object that refers to an instance of bad_alloc.", but doesn't say anything about what should happen if memory allocation succeeds but the actual copying fails.

I see three alternatives: (1) return an exception_ptr object that refers to an instance of some fixed exception type, (2) return an exception_ptr object that refers to an instance of the copy ctor's thrown exception (but if that has a throwing copy ctor, an infinite loop can occur), or (3) call terminate().

I believe that terminate() is the most reasonable course of action, but before we go implement that, I wanted to raise this issue.

[ Peter's summary: ]

The current practice is to not have throwing copy constructors in exception classes, because this can lead to terminate() as described in 18.5.1 [except.terminate]. Thus calling terminate() in this situation seems consistent and does not introduce any new problems.

However, the resolution of core issue 475 may relax this requirement:

The CWG agreed with the position that std::uncaught_exception() should return false during the copy to the exception object and that std::terminate() should not be called if that constructor exits with an exception.

Since throwing copy constructors will no longer call terminate(), option (3) doesn't seem reasonable as it is deemed too drastic a response in a recoverable situation.

Option (2) cannot be adopted by itself, because a potential infinite recursion will need to be terminated by one of the other options.

Proposed resolution:

Add the following paragraph after 21.8.6 [propagation]/7:

Returns (continued): If the attempt to copy the current exception object throws an exception, the function returns an exception_ptr that refers to the thrown exception or, if this is not possible, to an instance of bad_exception.

[Note: The copy constructor of the thrown exception may also fail, so the implementation is allowed to substitute a bad_exception to avoid infinite recursion. -- end note.]

Rationale:

[ San Francisco: ]

Pete: there may be an implied assumption in the proposed wording that current_exception() copies the existing exception object; the implementation may not actually do that.

Pete will make the required editorial tweaks to rectify this.