1
0
Files
YYCCommonplace/doc/src/carton/ironpad.dox

110 lines
5.5 KiB
Plaintext
Raw Normal View History

2026-01-20 13:20:17 +08:00
namespace yycc::carton::ironpad {
/**
2026-01-20 13:20:17 +08:00
\page ironpad Unhandled Exception Handler
2026-01-20 13:20:17 +08:00
Most Linux users are familiar with using core dump to find bugs.
However finding bugs is a tough work on Windows especially most Windows users are naive for getting core dump.
So it is essential to make an easy-to-visit core dump feature for Windows program.
This is the reason why I create this module, yycc::carton::ironpad.
You may know Google also has a similar and universal project called Crashpad used by Google Chrome.
That's right. But it is too heavy.
I just want to implement a tiny but worked core dump feature on Windows.
This module is Windows specific.
2026-01-20 13:20:17 +08:00
It still be available on other operating systems but all of its functions are do nothing.
2026-01-20 13:20:17 +08:00
\section ironpad__usage Usage
2026-01-20 13:20:17 +08:00
\subsection ironpad__usage__code Register Code
2026-01-20 13:20:17 +08:00
In most scenarios, programmer only need call #startup when program started or module loaded.
And call #shutdown when program exited or module unloaded.
All details are hidden by these 2 feature.
Programmer do not need worried about the implementation of unhandled exception handler.
2026-01-20 13:20:17 +08:00
Optionally, you can provide a function pointer during calling #startup as a callback.
The prototype of this function pointer is #ExceptionCallback.
This callback will be called if any unhandled exception happened.
It provides 2 pathes to log file and core dump file respectively.
So that you can use an explicit way, e.g. \c MessageBox, to tell user exception happened and where are the log files,
especially in GUI application because the default output stream, \c stderr, is invisible in GUI application.
However, please note the pathes provided by callback may be empty.
In this case, it means that handler fail to create corresponding log files.
Also, if you trying to register unhandled exception handler on the same process in different module with different callback,
only the callback provided in first success registering will be called when unhandled exception happened,
2026-01-20 13:20:17 +08:00
due to \ref ironpad__notes__singleton design.
2026-01-20 13:20:17 +08:00
\subsection ironpad__usage__location Location
When unhandled exception occurs,
unhandled exception handler will try to record error log and core dump in following path:
2026-01-20 13:20:17 +08:00
\li Error Log: <TT>\%LOCALAPPDATA\%\\IronPad\\<I>program.exe</I>.<I>pid</I>.log</TT>
\li Core Dump: <TT>\%LOCALAPPDATA\%\\IronPad\\<I>program.exe</I>.<I>pid</I>.dmp</TT>
The italic characters <I>program.exe</I> and <I>pid</I> will be replaced by program name and process ID respectively at runtime.
2026-01-20 13:20:17 +08:00
Directory <TT>\%LOCALAPPDATA\%\\IronPad</TT> is the dedicated directory for this module.
So you may see the generated logs and dumps in it.
2026-01-20 13:20:17 +08:00
\subsection ironpad__usage__last_remedy Last Remedy
If unhandled exception handler occurs error, these stuff may not be generated correctly.
The end user may not find them and send them to you.
There is a last remedy for this scenario.
Unhandled exception handler will still output error log in \c stderr no matter whether error log or core dump is created.
So end user always can fetch error log from console.
You only need to instruct end user open command prompt, launch application, reproduce error and get the output error log in console.
In this case, you can not get core dump. But you can get error log.
It is not good for debugging but it is better than nothing.
Also please note the last remedy may still have a little bit possibility to occurs error and output nothing,
especially the error occurs in back trace function.
There is no guaranteen that unhandled exception handler must generate error log and core dump.
2026-01-20 13:20:17 +08:00
\section ironpad__notes Notes
2026-01-20 13:20:17 +08:00
\subsection ironpad__notes__thread_safe Thread Safe
2026-01-20 13:20:17 +08:00
All exposed functions in this namespace are thread safe.
The implementation uses \c std::mutex to ensure this.
2026-01-20 13:20:17 +08:00
\subsection ironpad__notes__singleton Singleton Handler
2026-01-20 13:20:17 +08:00
This namespace also have a mechanism that make sure the same unhandled exception handler implementation only appear once in the same process.
For example, you have an executable program A.exe, and 2 dynamic libraries B.dll and C.dll.
A.exe and B.dll use YYCC unhandled exception handler feature but C.dll not.
A.exe will load B.dll and C.dll at runtime.
2026-01-20 13:20:17 +08:00
Although both A.exe and B.dll call #startup,
when unhandled exception occurs, there is only one error report output,
which may be generated by A.exe or B.dll accoridng to their order of loading.
The core purpose of this is making sure the program will not output too many error report for the same unhandled exception,
2026-01-20 13:20:17 +08:00
no matter how many modules calling #startup are loaded.
Only one error report is enough.
More precisely, we use \c CreateMutexW to create an unique mutex in Windows global scope,
2026-01-20 13:20:17 +08:00
to make sure #startup only run once in the same process.
It is very like the implementation of singleton application.
2026-01-20 13:20:17 +08:00
\subsection ironpad__notes__recursive_calling Recursive Calling
The implementation of unhandled exception handler may also will throw exception.
This will cause infinite recursive calling.
2026-01-20 13:20:17 +08:00
This namespace has internal mechanism to prevent this bad case.
If this really happened, the handler will quit silent and will not cause any issue.
Programmer don't need to worry about this.
2026-01-20 13:20:17 +08:00
\subsection ironpad__notes__user_callback The Timing of User Callback
The timing of calling user callback is the tail of unhandled exception handler.
It means that all log and coredump have been written if possible before calling callback.
Because user callback may still raise exception.
We want all essential log files has been written before calling it,
so that at least we can visit them on disk or console.
*/
}