Sunday, October 24, 2021

[SOLVED] How GCC (libstdc++) runtime decides to terminate() while an exception is active

Issue

We know that terminate() is called if an exception is currently active and there is another call to throw.

Want to understand what causes this to be differentiated from a situation when a catch block does a throw from with-in? I am assuming that a if a catch block is executing, it signifies of an active exception.

class exception_type{}

try{ ... throw obj; ... 
}catch(exception_type& obj){
 ...
 ... 
 throw x;
 ...
}

From this code sample, since we have another throw here in catch block, which should get caught by another handler in the dynamically enclosing try block. So this seems to be a valid use of a throw inside catch. But at this moment we already have a an exception active. Why should not it cause terminate() to be called? Or in other words, how exactly the gcc's c++ runtime would recognize that there is already an exception active and a terminate() needs to be called.


Solution

The credit for this answer goes to @HolyBlackCat who has hinted this in his answer.

The response of a throw is a complex process in which C++ run-time needs to perform several distinct actions. Though the actual process may be defined by run-time's implementation but few things could be understood in common. This paper could shed some more light. Please see section 3.3.

In the process of servicing a throw, a search for appropriate catch is initiated. This in itself may cause unwinding of the current stack frame. The side effect of unwinding a stack frame is that corresponding destructors for objects in current frame be called. This action of calling a destructor again lands run-time in user's code area(unsafe). After this is done, we again enter in the run-time's territory(safer).

Finally when a suitable catch is entered, the active exception is destroyed and it starts executing handler's code. For this reason the throw as shown in question, would not experience any active exception.

This also explains why we should not throw an exception from a destructor which goes out of scope. It would actually be a good practice to have a try{....}catch(...) block in destructor to safeguard from any untoward terminate() incidents.



Answered By - ultimate cause