Title
std::terminate problem
Status
resolved
Section
[exception.terminate]
Submitter
Daniel Krügler

Created on 2011-09-25.00:00:00 last changed 1 week ago

Messages

Date: 2024-11-07.00:00:00

[ 2024-11-07 Status changed: Open → Resolved. ]

Resolved by the resolution of LWG 2111.

Date: 2012-02-27.16:24:02

[ 2012, Kona ]

Move to Open.

There is an interaction with Core issues in this area that Jens is already supplying wording for. Review this issue again once Jens wording is available.

Alisdair to review clause 15.5 (per Jens suggestion) and recommend any changes, then integrate Jens wording into this issue.

Date: 2011-12-09.00:00:00

[ 2011-12-09: Daniel comments ]

A related issue is 2111.

Date: 2011-09-25.00:00:00

Andrzej Krzemienski reported the following on comp.std.c++:

In N3290, which is to become the official standard, in [terminate], paragraph 1 reads

Remarks: Called by the implementation when exception handling must be abandoned for any of several reasons (15.5.1), in effect immediately after evaluating the throw-expression (18.8.3.1). May also be called directly by the program.

It is not clear what is "in effect". It was clear in previous drafts where paragraphs 1 and 2 read:

Called by the implementation when exception handling must be abandoned for any of several reasons (15.5.1). May also be called directly by the program.

Effects: Calls the terminate_handler function in effect immediately after evaluating the throw-expression (18.8.3.1), if called by the implementation, or calls the current terminate_handler function, if called by the program.

It was changed by N3189. The same applies to function unexpected (D. 11.4, paragraph 1).

Assuming the previous wording is still intended, the wording can be read "unless std::terminate is called by the program, we will use the handler that was in effect immediately after evaluating the throw-expression".

This assumes that there is some throw-expression connected to every situation that triggers the call to std::terminate. But this is not the case:

  • In case std::thread is assigned to or destroyed while being joinable there is no throw-expression involved.
  • In case std::unexpected is called by the program, std::terminate is triggered by the implementation - no throw-expression involved.
  • In case a destructor throws during stack unwinding we have two throw-expressions involved.

Which one is referred to?

In case std::nested_exception::rethrow_nested is called for an object that has captured no exception, there is no throw-expression involved directly (and may no throw be involved even indirectly).

Next, [terminate.handler], paragraph 2 says

Required behavior: A terminate_handler shall terminate execution of the program without returning to the caller.

This seems to allow that the function may exit by throwing an exception (because word "return" implies a normal return).

One could argue that words "terminate execution of the program" are sufficient, but then why "without returning to the caller" would be mentioned. In case such handler throws, noexcept specification in function std::terminate is violated, and std::terminate would be called recursively - should std::abort not be called in case of recursive std::terminate call? On the other hand some controlled recursion could be useful, like in the following technique.

The here mentioned wording changes by N3189 in regard to [terminate] p1 were done for a better separation of effects (Effects element) and additional normative wording explanations (Remarks element), there was no meaning change intended. Further, there was already a defect existing in the previous wording, which was not updated when further situations where defined, when std::terminate where supposed to be called by the implementation.

The part

"in effect immediately after evaluating the throw-expression"

should be removed and the quoted reference to [terminate.handler] need to be part of the effects element where it refers to the current terminate_handler function, so should be moved just after

"Effects: Calls the current terminate_handler function."

It seems ok to allow a termination handler to exit via an exception, but the suggested idiom should better be replaced by a more simpler one based on evaluating the current exception pointer in the terminate handler, e.g.

void our_terminate (void) {
  std::exception_ptr p = std::current_exception();
  if (p) {
    ... // OK to rethrow and to determine it's nature
  } else {
    ... // Do something else
  }
}
History
Date User Action Args
2024-11-07 13:05:21adminsetmessages: + msg14449
2024-11-07 13:05:21adminsetstatus: open -> resolved
2012-02-27 16:24:02adminsetmessages: + msg6022
2012-02-12 18:36:43adminsetstatus: new -> open
2011-12-09 17:58:13adminsetmessages: + msg5959
2011-09-25 00:00:00admincreate