The Solution
I had to decouple the information about the catch and throw points from the exception being thrown. Because each exception is processed by the thread that throws it, I decided to store the catch and throw points in a list coupled to the active thread.
This means that each time an exception is caught and thrown, then the information related to the catch and throw point are added to a list coupled to the active thread and the original exception is thrown again, unmodified.
The first catch statement that is able to handle the error can then retrieve a list of all the points traversed by the exception by analyzing the current thread's "catch and throw" list.
The Implementation
The source code provides two macros to be placed at the very beginning and at the very end of the application's functions, and a statically allocated object called exceptionsManager
that logs all the information related to the catch and throw points, organized by thread.
The two macros that have to wrap the functions that need to be monitored are called FUNCTION_START and FUNCTION_END; they wrap the body of the functions in a try block.
FUNCTION_START also allocates a constant string that stores the function's name, while the macro FUNCTION_END contains the catch block that catches all the exceptions uncaught by the function. The catch block calls a method in the exceptionsManager
object to store all the relevant information and then re-throws the caught exception.
The information stored in the exceptionsManager
includes: the function name, the file name and the line number where the catch and throw takes place, the exception's type, and the exception's message (if any).
All the information is piled up until a call to exceptionsManager::getExceptionInfo()
is made.
getExceptionInfo()
is usually called from the catch block that can process the exception; the function returns a list containing the information about all the catch and throw points traversed by the caught exception and also clears the list in the exceptionsManager
.