Skip to content

Commit 4faf3f6

Browse files
committed
improved crash handler (more verbose)
1 parent e7ca501 commit 4faf3f6

File tree

7 files changed

+119
-58
lines changed

7 files changed

+119
-58
lines changed

sources/libcore/concurrent/concurrent.cpp

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include <atomic>
22
#include <cerrno>
33
#include <exception>
4-
#include <mutex>
54
#include <thread>
65

76
#ifdef CAGE_SYSTEM_WINDOWS
@@ -20,6 +19,7 @@
2019
#include <semaphore.h>
2120
#include <sys/types.h>
2221
#include <unistd.h>
22+
#include <mutex>
2323
#endif
2424

2525
#ifdef CAGE_SYSTEM_LINUX
@@ -36,10 +36,6 @@
3636

3737
namespace cage
3838
{
39-
#ifdef CAGE_SYSTEM_LINUX
40-
void crashHandlerInstallAltStack();
41-
#endif
42-
4339
namespace
4440
{
4541
class MutexImpl : public Mutex
@@ -658,36 +654,19 @@ namespace cage
658654
return systemMemory().createImpl<Thread, ThreadImpl>(func, threadName);
659655
}
660656

657+
void crashHandlerThreadInit();
658+
661659
namespace
662660
{
663-
#ifdef CAGE_SYSTEM_WINDOWS
664-
void currentThreadStackGuardLimit()
665-
{
666-
ULONG v = 128 * 1024;
667-
SetThreadStackGuarantee(&v);
668-
}
669-
670-
struct SetupStackGuardLimit
671-
{
672-
SetupStackGuardLimit() { currentThreadStackGuardLimit(); }
673-
} setupStackGuardLimit;
674-
#endif
675-
676661
#ifdef CAGE_SYSTEM_WINDOWS
677662
DWORD WINAPI threadFunctionImpl(LPVOID params)
678663
#else
679664
void *threadFunctionImpl(void *params)
680665
#endif
681666
{
682667
ThreadImpl *impl = (ThreadImpl *)params;
683-
#ifdef CAGE_SYSTEM_WINDOWS
684-
currentThreadStackGuardLimit();
685-
#endif
686-
#ifdef CAGE_SYSTEM_LINUX
687-
crashHandlerInstallAltStack();
688-
#endif
689-
690668
currentThreadName(impl->threadName);
669+
crashHandlerThreadInit();
691670
try
692671
{
693672
impl->function();

sources/libcore/concurrent/process.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ extern "C"
2727
{
2828
CAGE_API_EXPORT DWORD WINAPI CageRemoteThreadEntryPointToRaiseSignalTerm(_In_ LPVOID)
2929
{
30+
try
31+
{
32+
using namespace cage;
33+
CAGE_LOG(SeverityEnum::Warning, "process", "raising SIGTERM");
34+
}
35+
catch (...)
36+
{
37+
// nothing
38+
}
3039
raise(SIGTERM);
3140
return 0;
3241
}

sources/libcore/crashHandlerLinux.cpp renamed to sources/libcore/errors/crashHandlerLinux.cpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ namespace cage
1919

2020
int crashHandlerLogFileFd = STDERR_FILENO;
2121

22-
void crashHandlerInstallAltStack()
22+
void crashHandlerThreadInit()
2323
{
24+
// install alternative stack memory for handling signals
25+
2426
static constexpr size_t AltStackSize = 128 * 1024; // bigger than SIGSTKSZ for safety
2527

2628
{
@@ -43,18 +45,19 @@ namespace cage
4345
if (sigaltstack(&ss, nullptr) != 0)
4446
{
4547
CAGE_LOG(SeverityEnum::Note, "crash-handler", strerror(errno));
46-
CAGE_LOG(SeverityEnum::Warning, "crash-handler", "failed to install alt stack");
48+
CAGE_LOG(SeverityEnum::Warning, "crash-handler", "failed to install thread alt stack");
49+
// most signals can be handled on regular stack memory, so we continue
4750
}
4851
}
4952

5053
namespace
5154
{
52-
constexpr int OldHandlersCount = 16;
53-
struct sigaction prevHandlers[OldHandlersCount] = {};
55+
constexpr int PrevHandlersCount = 16;
56+
struct sigaction prevHandlers[PrevHandlersCount] = {};
5457

5558
struct sigaction *prevHandler(int sig)
5659
{
57-
if (sig >= 0 && sig < OldHandlersCount)
60+
if (sig >= 0 && sig < PrevHandlersCount)
5861
return &prevHandlers[sig];
5962
return nullptr;
6063
}
@@ -77,6 +80,8 @@ namespace cage
7780
return "SIGTRAP";
7881
case SIGTERM:
7982
return "SIGTERM";
83+
case SIGINT:
84+
return "SIGINT";
8085
default:
8186
return "UNKNOWN";
8287
}
@@ -102,35 +107,20 @@ namespace cage
102107
safeWrite("\n");
103108
}
104109

105-
void crashHandler(int sig, siginfo_t *si, void *uctx)
110+
void performPreviousHandler(int sig, siginfo_t *si, void *uctx)
106111
{
107-
safeWrite(Stringizer() + "signal handler: " + sigToStr(sig) + " (" + sig + ")\n");
108-
109-
if (si)
110-
safeWrite(Stringizer() + "fault addr: " + (uintptr_t)si->si_addr + ", code: " + si->si_code + "\n");
111-
112-
safeWrite(Stringizer() + "in thread: " + currentThreadName() + "\n");
113-
printStackTrace();
114-
115112
if (struct sigaction *prev = prevHandler(sig))
116113
{
117114
safeWrite("calling previous handler\n");
118115
if (prev->sa_flags & SA_SIGINFO)
119-
{
120-
// previous handler expects 3 arguments
121116
prev->sa_sigaction(sig, si, uctx);
122-
}
123117
else if (prev->sa_handler == SIG_DFL || prev->sa_handler == SIG_IGN)
124118
{
125-
// default or ignore: you can reset signal to default and raise
126119
signal(sig, prev->sa_handler);
127120
raise(sig);
128121
}
129122
else
130-
{
131-
// simple handler with 1 argument
132123
prev->sa_handler(sig);
133-
}
134124
}
135125
else
136126
{
@@ -140,10 +130,27 @@ namespace cage
140130
}
141131
}
142132

133+
void crashHandler(int sig, siginfo_t *si, void *uctx)
134+
{
135+
safeWrite(Stringizer() + "signal handler: " + sigToStr(sig) + " (" + sig + ")\n");
136+
if (si)
137+
safeWrite(Stringizer() + "fault addr: " + (uintptr_t)si->si_addr + ", code: " + si->si_code + "\n");
138+
safeWrite(Stringizer() + "in thread: " + currentThreadName() + "\n");
139+
printStackTrace();
140+
performPreviousHandler(sig, si, uctx);
141+
}
142+
143+
void intHandler(int sig, siginfo_t *si, void *uctx)
144+
{
145+
safeWrite(Stringizer() + "signal handler: " + sigToStr(sig) + " (" + sig + ")\n");
146+
performPreviousHandler(sig, si, uctx);
147+
}
148+
149+
template<auto Handler>
143150
void installHandler(int sig)
144151
{
145152
struct sigaction sa = {};
146-
sa.sa_sigaction = &crashHandler;
153+
sa.sa_sigaction = Handler;
147154
sigemptyset(&sa.sa_mask);
148155
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
149156
if (sigaction(sig, &sa, prevHandler(sig)) != 0)
@@ -157,10 +164,11 @@ namespace cage
157164
{
158165
SetupHandlers()
159166
{
160-
crashHandlerInstallAltStack();
161-
int signals[] = { SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP };
162-
for (int s : signals)
163-
installHandler(s);
167+
crashHandlerThreadInit();
168+
for (int s : { SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP })
169+
installHandler<&crashHandler>(s);
170+
for (int s : { SIGTERM, SIGINT })
171+
installHandler<&intHandler>(s);
164172
}
165173
} setupHandlers;
166174
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifdef CAGE_SYSTEM_MAC
2+
3+
#include <cage-core/core.h>
4+
5+
namespace cage
6+
{
7+
void crashHandlerThreadInit()
8+
{
9+
// nothing for now
10+
}
11+
12+
namespace
13+
{
14+
struct SetupHandlers
15+
{
16+
SetupHandlers() { crashHandlerThreadInit(); }
17+
} setupHandlers;
18+
}
19+
}
20+
21+
#endif // CAGE_SYSTEM_MAC

sources/libcore/crashHandlerWindows.cpp renamed to sources/libcore/errors/crashHandlerWindows.cpp

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#ifdef CAGE_SYSTEM_WINDOWS
22

3-
#include <mutex>
4-
#include "windowsMinimumInclude.h"
3+
#include "../windowsMinimumInclude.h"
54
#include <DbgHelp.h>
65

76
#pragma comment(lib, "DbgHelp.lib")
@@ -10,9 +9,17 @@
109
#define EXCEPTION_RENAME_THREAD 0x406D1388
1110

1211
#include <cage-core/core.h>
12+
#include <cage-core/concurrent.h>
1313

1414
namespace cage
1515
{
16+
void crashHandlerThreadInit()
17+
{
18+
// reserve safe memory on the stack for handling EXCEPTION_STACK_OVERFLOW
19+
ULONG v = 128 * 1024;
20+
SetThreadStackGuarantee(&v);
21+
}
22+
1623
namespace
1724
{
1825
String exceptionCodeToString(uint64 code)
@@ -112,6 +119,25 @@ namespace cage
112119
}
113120
}
114121

122+
String consoleCodeToString(uint64 code)
123+
{
124+
switch (code)
125+
{
126+
case CTRL_C_EVENT:
127+
return "CTRL_C_EVENT";
128+
case CTRL_BREAK_EVENT:
129+
return "CTRL_BREAK_EVENT";
130+
case CTRL_CLOSE_EVENT:
131+
return "CTRL_CLOSE_EVENT";
132+
case CTRL_LOGOFF_EVENT:
133+
return "CTRL_LOGOFF_EVENT";
134+
case CTRL_SHUTDOWN_EVENT:
135+
return "CTRL_SHUTDOWN_EVENT";
136+
default:
137+
return Stringizer() + "unknown console code: " + code;
138+
}
139+
}
140+
115141
bool ignoredExceptionCodes(uint64 code)
116142
{
117143
switch (code)
@@ -200,12 +226,17 @@ namespace cage
200226
}
201227
}
202228

229+
RecursiveMutex *handlerMutex()
230+
{
231+
static Holder<RecursiveMutex> *mut = new Holder<RecursiveMutex>(newRecursiveMutex()); // this leak is intentional
232+
return +*mut;
233+
}
234+
203235
void commonHandler(PEXCEPTION_POINTERS ex)
204236
{
205237
if (IsDebuggerPresent())
206238
return;
207-
static std::mutex mutex;
208-
std::scoped_lock lock(mutex);
239+
ScopeLock lock(handlerMutex());
209240
CAGE_LOG(SeverityEnum::Error, "crash-handler", Stringizer() + "crash handler: " + exceptionCodeToString(ex->ExceptionRecord->ExceptionCode));
210241
if (ex->ExceptionRecord->ExceptionCode == EXCEPTION_DOTNET)
211242
return;
@@ -221,6 +252,7 @@ namespace cage
221252
for (uint32 i = 0; i < ex->ExceptionRecord->NumberParameters; i++)
222253
CAGE_LOG(SeverityEnum::Info, "crash-handler", Stringizer() + "parameter[" + i + "]: " + ex->ExceptionRecord->ExceptionInformation);
223254
}
255+
CAGE_LOG(SeverityEnum::Info, "crash-handler", Stringizer() + "in thread: " + currentThreadName());
224256
printStackTrace(ex);
225257
}
226258

@@ -241,13 +273,25 @@ namespace cage
241273
return EXCEPTION_CONTINUE_SEARCH;
242274
}
243275

276+
BOOL WINAPI consoleHandler(DWORD code)
277+
{
278+
CAGE_LOG(SeverityEnum::Error, "crash-handler", Stringizer() + "crash handler: " + consoleCodeToString(code));
279+
return FALSE; // let other handlers process it
280+
}
281+
244282
struct SetupHandlers
245283
{
246284
SetupHandlers()
247285
{
248-
AddVectoredExceptionHandler(1, &vectoredHandler);
249-
AddVectoredContinueHandler(1, &vectoredHandler);
286+
handlerMutex(); // allocate the mutex upfront
287+
crashHandlerThreadInit();
288+
if (!AddVectoredExceptionHandler(1, &vectoredHandler))
289+
CAGE_THROW_ERROR(SystemError, "AddVectoredExceptionHandler", GetLastError());
290+
if (!AddVectoredContinueHandler(1, &vectoredHandler))
291+
CAGE_THROW_ERROR(SystemError, "AddVectoredContinueHandler", GetLastError());
250292
previous = SetUnhandledExceptionFilter(&unhandledHandler);
293+
if (!SetConsoleCtrlHandler(&consoleHandler, TRUE))
294+
CAGE_THROW_ERROR(SystemError, "SetConsoleCtrlHandler", GetLastError());
251295
}
252296
} setupHandlers;
253297
}

sources/libcore/debug.cpp renamed to sources/libcore/errors/debug.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ static_assert(CAGE_DEBUG_BOOL == false);
2323
#include <string> // std::getline
2424

2525
#ifdef CAGE_SYSTEM_WINDOWS
26-
#include "windowsMinimumInclude.h"
26+
#include "../windowsMinimumInclude.h"
2727
#include <intrin.h> // __debugbreak
2828
#endif
2929

File renamed without changes.

0 commit comments

Comments
 (0)