Skip to content

Commit bddb5d9

Browse files
fix(crash_handler): add g_dumpWritten latch to prevent duplicate SIGSEGV dumps on repeated handler invocation
Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/ec8eb5f9-a370-4c4b-b106-2a543b35f72f Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
1 parent 043034c commit bddb5d9

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

osu.Android/Native/crash_handler.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ volatile sig_atomic_t g_installed = 0;
104104
// the previous handler instead of recursing.
105105
volatile sig_atomic_t g_inHandler = 0;
106106

107+
// Permanent "dump written" latch. Set to 1 the first time we successfully
108+
// begin writing a dump; never reset. Prevents a second full dump being
109+
// written if the crash handler is somehow re-invoked in the same process
110+
// lifetime (e.g. Mono re-raises SIGSEGV via tgkill after our handler chains
111+
// to it, and our handler gets re-installed between the two deliveries).
112+
// Unlike g_inHandler this is intentionally NOT cleared before the re-raise.
113+
volatile sig_atomic_t g_dumpWritten = 0;
114+
107115
// ----------------------------------------------------------------------------
108116
// Async-signal-safe formatters (no malloc, no stdio, no locale).
109117
// ----------------------------------------------------------------------------
@@ -983,6 +991,28 @@ static void crashHandler(int sig, siginfo_t* info, void* ucontext) {
983991
}
984992
g_inHandler = 1;
985993

994+
// Duplicate-dump guard. If we already wrote a dump for this process
995+
// lifetime (e.g. the handler was re-invoked after Mono re-raised the
996+
// signal), skip the dump but still chain to the previous handler so the
997+
// system tombstone is produced. Unlike g_inHandler this latch is never
998+
// cleared — one dump per crash, not one dump per signal delivery.
999+
if (g_dumpWritten) {
1000+
bool restored = false;
1001+
for (size_t i = 0; i < kNumSignals; ++i) {
1002+
if (kSignals[i] == sig) {
1003+
restored = (sigaction(sig, &g_prevHandlers[i], nullptr) == 0);
1004+
break;
1005+
}
1006+
}
1007+
// If sigaction failed we cannot chain cleanly — fall back to default
1008+
// disposition so the process at least terminates and debuggerd runs.
1009+
if (!restored) signal(sig, SIG_DFL);
1010+
g_inHandler = 0;
1011+
raise(sig);
1012+
return;
1013+
}
1014+
g_dumpWritten = 1;
1015+
9861016
// Open the dump file (append). If g_logPath is empty we still log to logcat.
9871017
//
9881018
// Pre-rotate runaway: if the existing log is more than 4× the soft cap

0 commit comments

Comments
 (0)