From 073ef0f393ff4297e8d48a72f30a605c2d272289 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Tue, 6 Jan 2026 11:05:50 +0000 Subject: [PATCH] std.Thread: mask all signals before unmapping stack As the comment explains, if a signal were to arrive between a detached thread's `munmap` and `exit` calls, the signal handler would immediately trigger SIGSEGV due to the stack being unmapped. To solve this, we need to block all signals before entering this logic. The musl implementation which this logic was ported from does this exact thing; that logic was just lost when porting. Notably, this would lead to a crash with no stack trace, because the SIGSEGV handler would itself crash due to the missing stack. --- lib/std/Thread.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig index 126338e77f0a82eae15042c49a20c3155d677faf..1c361506b72e3eb1a8c6125642b68ba1e6fba51a 100644 --- a/lib/std/Thread.zig +++ b/lib/std/Thread.zig @@ -1224,6 +1224,10 @@ const LinuxThreadImpl = struct { /// Ported over from musl libc's pthread detached implementation: /// https://github.com/ifduyue/musl/search?q=__unmapself fn freeAndExit(self: *ThreadCompletion) noreturn { + // If a signal were delivered between SYS_munmap and SYS_exit, any installed signal + // handler would immediately segfault due to the stack being unmapped. To avoid this, + // we need to mask all signals before entering the inline asm. + posix.sigprocmask(std.posix.SIG.BLOCK, &std.os.linux.sigfillset(), null); switch (target.cpu.arch) { .x86 => asm volatile ( \\ movl $91, %%eax # SYS_munmap -- 2.54.0