fix(backward): Add std::atomic for Windows to prevent deadlock in Deb…
…ug due to CRT's SIGABRT handler behaviour
Scenario:
- On Windows, the first crash is handled via UnhandledExceptionFilter -> crash_handler(EXCEPTION_POINTERS*), which wakes the reporter thread to collect and print the stack trace.
- After printing, our handler calls abort(). In Debug CRT, abort raises SIGABRT and invokes our installed signal handler again.
- On this second entry, crash_handler(int) sets crashed() = crash_status::crashed and waits on the condition variable. But the reporter thread has already finished (set crashed() = ending) and exited, so no one flips the state anymore. The wait blocks forever, causing a deadlock that only reproduces in Debug.
Fix
- Add atomic reentry guard to ensure crash handling runs only once across all entry points (SEH, SIGABRT, terminate and invalid parameter). Where subsequent entries return to prevent deadlock.
My instinct tells me backward-cpp shouldn't be responsible for this thread synchronization. But I could be wrong.
Wouldn't it be more reasonable to handle this reentrant situation in your signal handlers? Not backward-cpp?
I am struggling to estimate the consequences of adding such a synchronisation to backward-cpp. Furthermore it won't work for C++98. Though I could be convinced that C++11 is the new baseline after all this time.
On Tue, Aug 26, 2025, 07:02 Thomas Reynders @.***> wrote:
…ug due to CRT's SIGABRT handler behaviour
Scenario:
- On Windows, the first crash is handled via UnhandledExceptionFilter -> crash_handler(EXCEPTION_POINTERS*), which wakes the reporter thread to collect and print the stack trace.
- After printing, our handler calls abort(). In Debug CRT, abort raises SIGABRT and invokes our installed signal handler again.
- On this second entry, crash_handler(int) sets crashed() = crash_status::crashed and waits on the condition variable. But the reporter thread has already finished (set crashed() = ending) and exited, so no one flips the state anymore. The wait blocks forever, causing a deadlock that only reproduces in Debug.
Fix
- Add atomic reentry guard to ensure crash handling runs only once across all entry points (SEH, SIGABRT, terminate and invalid parameter). Where subsequent entries return to prevent deadlock.
You can view, comment on, or merge this pull request online at:
https://github.com/bombela/backward-cpp/pull/357 Commit Summary
- 33506dd https://github.com/bombela/backward-cpp/pull/357/commits/33506dd4bf8a5109ffca57798491d2720ddc7f05 fix(backward): Add std::atomic for Windows to prevent deadlock in Debug due to CRT's SIGABRT handler behaviour
File Changes
(1 file https://github.com/bombela/backward-cpp/pull/357/files)
- M backward.hpp https://github.com/bombela/backward-cpp/pull/357/files#diff-9cee89cb5e596480ab8d068475a6dc41356808be8dc55f8052a808910fd04ddb (37)
Patch Links:
- https://github.com/bombela/backward-cpp/pull/357.patch
- https://github.com/bombela/backward-cpp/pull/357.diff
— Reply to this email directly, view it on GitHub https://github.com/bombela/backward-cpp/pull/357, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABUZDFWTF5ZG5AI2A244G33PRSGZAVCNFSM6AAAAACE3EGB42VHI2DSMVQWIX3LMV43ASLTON2WKOZTGM2TKNZYHAYTANQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>
Hi @bombela
My instinct tells me backward-cpp shouldn't be responsible for this thread synchronization. But I could be wrong. Wouldn't it be more reasonable to handle this reentrant situation in your signal handlers? Not backward-cpp?
In my situation I use backward-cpp as my signal handlers for capturing crashes, but it is an interesting though. On the contrary, backward-cpp creates the thread, so handling situation to avoid deadlocks only seems reasonable to me.
For me it is also difficult to see the impact of the change and I was hoping you could help me with that 😄, which is why I only chose to implement the fix for c++11. On the note of c++ I personally would vouch for the absolute minimal required c++ version to be 11.
Thank you for time.