authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-07 01:11:25+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-07 01:11:25+01:00
log1bef876636ab96449703ad2e8f9f22918546e99c
tree82f530c5feab4862e7c0b796d816ba2f3995409b
parentfa625e878f3f8f8b2dbc1d8ca0b761fb65326d02
parentbe0a77efd2aad5108d3357914cbc71f560ea0161

Merge pull request 'std.Thread: mask all signals before unmapping stack' (#30713) from detached-thread-exit-signal-race into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/30713 Reviewed-by: Andrew Kelley <andrew@ziglang.org>

4 files changed, 12 insertions(+), 6 deletions(-)

lib/std/Io/test.zig-4
...@@ -254,8 +254,6 @@ test "Group.cancel" {...@@ -254,8 +254,6 @@ test "Group.cancel" {
254}254}
255255
256test "Group.concurrent" {256test "Group.concurrent" {
257 if (builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30096
258
259 const io = testing.io;257 const io = testing.io;
260258
261 var group: Io.Group = .init;259 var group: Io.Group = .init;
...@@ -421,8 +419,6 @@ test "Event" {...@@ -421,8 +419,6 @@ test "Event" {
421}419}
422420
423test "recancel" {421test "recancel" {
424 if (builtin.os.tag == .linux and !builtin.link_libc) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30592
425
426 const global = struct {422 const global = struct {
427 fn worker(io: Io) Io.Cancelable!void {423 fn worker(io: Io) Io.Cancelable!void {
428 var dummy_event: Io.Event = .unset;424 var dummy_event: Io.Event = .unset;
lib/std/Thread.zig+4
...@@ -1224,6 +1224,10 @@ const LinuxThreadImpl = struct {...@@ -1224,6 +1224,10 @@ const LinuxThreadImpl = struct {
1224 /// Ported over from musl libc's pthread detached implementation:1224 /// Ported over from musl libc's pthread detached implementation:
1225 /// https://github.com/ifduyue/musl/search?q=__unmapself1225 /// https://github.com/ifduyue/musl/search?q=__unmapself
1226 fn freeAndExit(self: *ThreadCompletion) noreturn {1226 fn freeAndExit(self: *ThreadCompletion) noreturn {
1227 // If a signal were delivered between SYS_munmap and SYS_exit, any installed signal
1228 // handler would immediately segfault due to the stack being unmapped. To avoid this,
1229 // we need to mask all signals before entering the inline asm.
1230 posix.sigprocmask(std.posix.SIG.BLOCK, &std.os.linux.sigfillset(), null);
1227 switch (target.cpu.arch) {1231 switch (target.cpu.arch) {
1228 .x86 => asm volatile (1232 .x86 => asm volatile (
1229 \\ movl $91, %%eax # SYS_munmap1233 \\ movl $91, %%eax # SYS_munmap
lib/std/crypto/argon2.zig-2
...@@ -907,8 +907,6 @@ test "kdf" {...@@ -907,8 +907,6 @@ test "kdf" {
907}907}
908908
909test "phc format hasher" {909test "phc format hasher" {
910 if (true) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30682
911
912 const allocator = std.testing.allocator;910 const allocator = std.testing.allocator;
913 const password = "testpass";911 const password = "testpass";
914 const io = std.testing.io;912 const io = std.testing.io;
lib/std/debug.zig+8
...@@ -532,6 +532,10 @@ pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn {...@@ -532,6 +532,10 @@ pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn {
532 else => {},532 else => {},
533 }533 }
534534
535 // Don't try to cancel during a panic. No need to re-enable cancelation,
536 // because the panic handler doesn't return.
537 _ = std.Options.debug_io.swapCancelProtection(.blocked);
538
535 if (enable_segfault_handler) {539 if (enable_segfault_handler) {
536 // If a segfault happens while panicking, we want it to actually segfault, not trigger540 // If a segfault happens while panicking, we want it to actually segfault, not trigger
537 // the handler.541 // the handler.
...@@ -1533,6 +1537,10 @@ fn handleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noret...@@ -1533,6 +1537,10 @@ fn handleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noret
1533}1537}
15341538
1535pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noreturn {1539pub fn defaultHandleSegfault(addr: ?usize, name: []const u8, opt_ctx: ?CpuContextPtr) noreturn {
1540 // Don't try to cancel during a segfault. No need to re-enable cancelation,
1541 // because the segfault handler doesn't return.
1542 _ = std.Options.debug_io.swapCancelProtection(.blocked);
1543
1536 // There is very similar logic to the following in `defaultPanic`.1544 // There is very similar logic to the following in `defaultPanic`.
1537 switch (panic_stage) {1545 switch (panic_stage) {
1538 0 => {1546 0 => {