Skip to content

Commit 87c02c3

Browse files
committed
improve crash handler on linux
1 parent 6cca486 commit 87c02c3

File tree

2 files changed

+64
-36
lines changed

2 files changed

+64
-36
lines changed

sources/libcore/concurrent/concurrent.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636

3737
namespace cage
3838
{
39+
#ifdef CAGE_SYSTEM_LINUX
40+
void crashHandlerInstallAltStack();
41+
#endif
42+
3943
namespace
4044
{
4145
class MutexImpl : public Mutex
@@ -679,6 +683,10 @@ namespace cage
679683
#ifdef CAGE_SYSTEM_WINDOWS
680684
currentThreadStackGuardLimit();
681685
#endif
686+
#ifdef CAGE_SYSTEM_LINUX
687+
crashHandlerInstallAltStack();
688+
#endif
689+
682690
currentThreadName(impl->threadName);
683691
try
684692
{

sources/libcore/crashHandlerLinux.cpp

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,48 @@
1111
#include <ucontext.h>
1212
#include <unistd.h>
1313

14-
#include <cage-core/core.h>
14+
#include <cage-core/core.h>
1515

1616
namespace cage
1717
{
18+
String currentThreadName();
19+
1820
int crashHandlerLogFileFd = STDERR_FILENO;
1921

22+
void crashHandlerInstallAltStack()
23+
{
24+
static constexpr size_t AltStackSize = 128 * 1024; // bigger than SIGSTKSZ for safety
25+
26+
{
27+
stack_t ss = {};
28+
if (sigaltstack(nullptr, &ss) == 0)
29+
{
30+
if ((ss.ss_flags & SS_DISABLE)==0 && ss.ss_size >= AltStackSize)
31+
return; // already installed and sufficient
32+
}
33+
}
34+
35+
void *altStackMem = mmap(nullptr, AltStackSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
36+
if (altStackMem == MAP_FAILED)
37+
altStackMem = std::malloc(AltStackSize); // fallback to malloc
38+
39+
stack_t ss{};
40+
ss.ss_sp = altStackMem;
41+
ss.ss_size = AltStackSize;
42+
ss.ss_flags = 0;
43+
if (sigaltstack(&ss, nullptr) != 0)
44+
{
45+
CAGE_LOG(SeverityEnum::Note, "crash-handler", strerror(errno));
46+
CAGE_LOG(SeverityEnum::Warning, "crash-handler", "failed to install alt stack");
47+
}
48+
}
49+
2050
namespace
21-
{
22-
void *altStackMem = nullptr;
51+
{
2352
constexpr int OldHandlersCount = 16;
24-
struct sigaction prevHandlers[OldHandlersCount] = {};
53+
struct sigaction prevHandlers[OldHandlersCount] = {};
2554

26-
struct sigaction *prevHandler(int sig)
55+
struct sigaction *prevHandler(int sig)
2756
{
2857
if (sig >= 0 && sig < OldHandlersCount)
2958
return &prevHandlers[sig];
@@ -56,29 +85,36 @@ namespace cage
5685
void safeWrite(const String &s)
5786
{
5887
write(crashHandlerLogFileFd, s.c_str(), s.length());
88+
if (crashHandlerLogFileFd!=STDERR_FILENO)
89+
write(STDERR_FILENO, s.c_str(), s.length());
5990
}
6091

6192
void printStackTrace()
6293
{
6394
// backtrace (best-effort; not strictly async-signal-safe)
64-
static constexpr int kMaxFrames = 256;
65-
void *frames[kMaxFrames];
66-
int n = backtrace(frames, kMaxFrames);
95+
static constexpr int MaxFrames = 256;
96+
void *frames[MaxFrames];
97+
int n = backtrace(frames, MaxFrames);
6798
safeWrite(Stringizer() + "stack trace:\n");
68-
backtrace_symbols_fd(frames, n, crashHandlerLogFileFd); // writes directly to fd
99+
backtrace_symbols_fd(frames, n, crashHandlerLogFileFd);
100+
if (crashHandlerLogFileFd!=STDERR_FILENO)
101+
backtrace_symbols_fd(frames, n, STDERR_FILENO);
102+
safeWrite("\n");
69103
}
70104

71105
void crashHandler(int sig, siginfo_t *si, void *uctx)
72106
{
73-
safeWrite(Stringizer() + "signal caught: " + sigToStr(sig) + " (" + sig + ")\n");
107+
safeWrite(Stringizer() + "signal handler: " + sigToStr(sig) + " (" + sig + ")\n");
74108

75109
if (si)
76110
safeWrite(Stringizer() + "fault addr: " + (uintptr_t)si->si_addr + ", code: " + si->si_code + "\n");
77111

112+
safeWrite(Stringizer() + "in thread: " + currentThreadName() + "\n");
78113
printStackTrace();
79114

80-
if (struct sigaction *prev = prevHandler(sig))
115+
if (struct sigaction *prev = prevHandler(sig))
81116
{
117+
safeWrite("calling previous handler\n");
82118
if (prev->sa_flags & SA_SIGINFO)
83119
{
84120
// previous handler expects 3 arguments
@@ -95,34 +131,18 @@ namespace cage
95131
// simple handler with 1 argument
96132
prev->sa_handler(sig);
97133
}
98-
}
99-
100-
// re-raise to trigger default handler (and core dump, if enabled)
101-
signal(sig, SIG_DFL);
102-
raise(sig);
103-
}
104-
105-
void installAltStack()
106-
{
107-
static constexpr size_t kAltStackSz = 128 * 1024; // bigger than SIGSTKSZ for safety
108-
altStackMem = mmap(nullptr, kAltStackSz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
109-
if (altStackMem == MAP_FAILED)
110-
altStackMem = std::malloc(kAltStackSz); // fallback to malloc
111-
stack_t ss{};
112-
ss.ss_sp = altStackMem;
113-
ss.ss_size = kAltStackSz;
114-
ss.ss_flags = 0;
115-
if (sigaltstack(&ss, nullptr) != 0)
116-
{
117-
CAGE_LOG(SeverityEnum::Info, "crash-handler", strerror(errno));
118-
CAGE_THROW_ERROR(Exception, "sigaltstack")
119-
}
134+
}
135+
else
136+
{
137+
safeWrite("calling default handler\n");
138+
signal(sig, SIG_DFL);
139+
raise(sig);
140+
}
120141
}
121142

122143
void installHandler(int sig)
123144
{
124-
struct sigaction sa
125-
{};
145+
struct sigaction sa = {};
126146
sa.sa_sigaction = &crashHandler;
127147
sigemptyset(&sa.sa_mask);
128148
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
@@ -137,7 +157,7 @@ namespace cage
137157
{
138158
SetupHandlers()
139159
{
140-
installAltStack();
160+
crashHandlerInstallAltStack();
141161
int signals[] = { SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, SIGTRAP };
142162
for (int s : signals)
143163
installHandler(s);

0 commit comments

Comments
 (0)