Skip to content

Commit 394d044

Browse files
committed
win: setup an alternate stack (fiber) for use in collecting backtraces
1 parent 053fc11 commit 394d044

File tree

1 file changed

+30
-15
lines changed

1 file changed

+30
-15
lines changed

src/signals-win.c

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,27 @@ void __cdecl crt_sig_handler(int sig, int num)
7777
}
7878
}
7979

80-
BOOL (*pSetThreadStackGuarantee)(PULONG);
80+
static JL_THREAD LPVOID collect_backtrace_fiber;
81+
static JL_THREAD PCONTEXT error_ctx;
82+
static VOID NOINLINE NORETURN CALLBACK start_backtrace_fiber(PVOID lpParameter)
83+
{
84+
while (1) {
85+
// collect the backtrace
86+
bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, error_ctx);
87+
// switch back to the execution fiber
88+
SwitchToFiber(jl_current_task->fiber);
89+
}
90+
}
91+
92+
static LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo);
8193
void restore_signals(void)
8294
{
95+
SetUnhandledExceptionFilter(exception_handler);
8396
SetConsoleCtrlHandler(NULL, 0); //turn on ctrl-c handler
97+
collect_backtrace_fiber = CreateFiberEx(sig_stack_size, sig_stack_size, FIBER_FLAG_FLOAT_SWITCH, start_backtrace_fiber, NULL);
8498
}
8599

86-
void jl_throw_in_ctx(jl_value_t *excpt, CONTEXT *ctxThread, int bt)
100+
void jl_throw_in_ctx(jl_value_t *excpt, PCONTEXT ctxThread)
87101
{
88102
assert(excpt != NULL);
89103
#if defined(_CPU_X86_64_)
@@ -93,7 +107,13 @@ void jl_throw_in_ctx(jl_value_t *excpt, CONTEXT *ctxThread, int bt)
93107
#else
94108
#error WIN16 not supported :P
95109
#endif
96-
bt_size = bt ? rec_backtrace_ctx(bt_data, MAX_BT_SIZE, ctxThread) : 0;
110+
if (excpt != jl_stackovf_exception) {
111+
bt_size = rec_backtrace_ctx(bt_data, MAX_BT_SIZE, ctxThread);
112+
}
113+
else {
114+
error_ctx = ctxThread;
115+
SwitchToFiber(collect_backtrace_fiber);
116+
}
97117
jl_exception_in_transit = excpt;
98118
#if defined(_CPU_X86_64_)
99119
*(DWORD64*)Rsp = 0;
@@ -137,7 +157,7 @@ static BOOL WINAPI sigint_handler(DWORD wsig) //This needs winapi types to guara
137157
jl_safe_printf("error: GetThreadContext failed\n");
138158
return 0;
139159
}
140-
jl_throw_in_ctx(jl_interrupt_exception, &ctxThread, 1);
160+
jl_throw_in_ctx(jl_interrupt_exception, &ctxThread);
141161
ctxThread.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
142162
if (!SetThreadContext(hMainThread,&ctxThread)) {
143163
jl_safe_printf("error: SetThreadContext failed\n");
@@ -153,20 +173,20 @@ static BOOL WINAPI sigint_handler(DWORD wsig) //This needs winapi types to guara
153173
return 1;
154174
}
155175

156-
static LONG WINAPI _exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo, int in_ctx)
176+
static LONG WINAPI _exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
157177
{
158178
if (ExceptionInfo->ExceptionRecord->ExceptionFlags == 0) {
159179
switch (ExceptionInfo->ExceptionRecord->ExceptionCode) {
160180
case EXCEPTION_INT_DIVIDE_BY_ZERO:
161181
fpreset();
162-
jl_throw_in_ctx(jl_diverror_exception, ExceptionInfo->ContextRecord,in_ctx);
182+
jl_throw_in_ctx(jl_diverror_exception, ExceptionInfo->ContextRecord);
163183
return EXCEPTION_CONTINUE_EXECUTION;
164184
case EXCEPTION_STACK_OVERFLOW:
165-
jl_throw_in_ctx(jl_stackovf_exception, ExceptionInfo->ContextRecord,in_ctx&&pSetThreadStackGuarantee);
185+
jl_throw_in_ctx(jl_stackovf_exception, ExceptionInfo->ContextRecord);
166186
return EXCEPTION_CONTINUE_EXECUTION;
167187
case EXCEPTION_ACCESS_VIOLATION:
168188
if (ExceptionInfo->ExceptionRecord->ExceptionInformation[0] == 1) { // writing to read-only memory (e.g. mmap)
169-
jl_throw_in_ctx(jl_readonlymemory_exception, ExceptionInfo->ContextRecord,in_ctx);
189+
jl_throw_in_ctx(jl_readonlymemory_exception, ExceptionInfo->ContextRecord);
170190
return EXCEPTION_CONTINUE_EXECUTION;
171191
}
172192
}
@@ -230,7 +250,7 @@ static LONG WINAPI _exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo,
230250

231251
static LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
232252
{
233-
return _exception_handler(ExceptionInfo,1);
253+
return _exception_handler(ExceptionInfo);
234254
}
235255

236256
#if defined(_CPU_X86_64_)
@@ -241,7 +261,7 @@ EXCEPTION_DISPOSITION _seh_exception_handler(PEXCEPTION_RECORD ExceptionRecord,
241261
ExceptionInfo.ContextRecord = ContextRecord;
242262

243263
EXCEPTION_DISPOSITION rval;
244-
switch (_exception_handler(&ExceptionInfo,1)) {
264+
switch (_exception_handler(&ExceptionInfo)) {
245265
case EXCEPTION_CONTINUE_EXECUTION:
246266
rval = ExceptionContinueExecution; break;
247267
case EXCEPTION_CONTINUE_SEARCH:
@@ -334,10 +354,6 @@ DLLEXPORT void jl_profile_stop_timer(void)
334354

335355
void jl_install_default_signal_handlers(void)
336356
{
337-
ULONG StackSizeInBytes = sig_stack_size;
338-
pSetThreadStackGuarantee = (BOOL (*)(PULONG)) jl_dlsym_e(jl_kernel32_handle, "SetThreadStackGuarantee");
339-
if (!pSetThreadStackGuarantee || !pSetThreadStackGuarantee(&StackSizeInBytes))
340-
pSetThreadStackGuarantee = NULL;
341357
if (signal(SIGFPE, (void (__cdecl *)(int))crt_sig_handler) == SIG_ERR) {
342358
jl_error("fatal error: Couldn't set SIGFPE");
343359
}
@@ -353,5 +369,4 @@ void jl_install_default_signal_handlers(void)
353369
if (signal(SIGTERM, (void (__cdecl *)(int))crt_sig_handler) == SIG_ERR) {
354370
jl_error("fatal error: Couldn't set SIGTERM");
355371
}
356-
SetUnhandledExceptionFilter(exception_handler);
357372
}

0 commit comments

Comments
 (0)