authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-01 11:38:06+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-01 11:38:06+02:00
log27611c10f8dc6a58161699a30a573459d855aede
tree42e6d115d9aacb0c8b453e8751bdf7e08c67dcdb
parent9b1eaad13fd331c4c2135f15ab9512b9e2342ff2
parent1226bb9268f20740a69afd3097d40b4d3e371647

Merge pull request 'LinuxThreadImpl fixups' (#31716) from blblack/zig:linux-thread-childtid into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31716 Reviewed-by: Alex Rønne Petersen <alex@alexrp.com>

2 files changed, 11 insertions(+), 1 deletions(-)

lib/std/Thread.zig+6-1
...@@ -1147,6 +1147,11 @@ const LinuxThreadImpl = struct {...@@ -1147,6 +1147,11 @@ const LinuxThreadImpl = struct {
1147 /// Ported over from musl libc's pthread detached implementation:1147 /// Ported over from musl libc's pthread detached implementation:
1148 /// https://github.com/ifduyue/musl/search?q=__unmapself1148 /// https://github.com/ifduyue/musl/search?q=__unmapself
1149 fn freeAndExit(self: *ThreadCompletion) noreturn {1149 fn freeAndExit(self: *ThreadCompletion) noreturn {
1150 // If we do not reset the child_tidptr to null here, the kernel would later write the
1151 // value zero to that address, which is inside the block we're unmapping below, after
1152 // our thread exits. This can sometimes corrupt memory in other mmap blocks from
1153 // unrelated concurrent threads.
1154 _ = linux.set_tid_address(null);
1150 // If a signal were delivered between SYS_munmap and SYS_exit, any installed signal1155 // If a signal were delivered between SYS_munmap and SYS_exit, any installed signal
1151 // handler would immediately segfault due to the stack being unmapped. To avoid this,1156 // handler would immediately segfault due to the stack being unmapped. To avoid this,
1152 // we need to mask all signals before entering the inline asm.1157 // we need to mask all signals before entering the inline asm.
...@@ -1484,7 +1489,7 @@ const LinuxThreadImpl = struct {...@@ -1484,7 +1489,7 @@ const LinuxThreadImpl = struct {
1484 }1489 }
14851490
1486 // Prepare the TLS segment and prepare a user_desc struct when needed on x861491 // Prepare the TLS segment and prepare a user_desc struct when needed on x86
1487 var tls_ptr = linux.tls.prepareArea(mapped[tls_offset..]);1492 var tls_ptr = linux.tls.prepareArea(mapped[tls_offset..][0..linux.tls.area_desc.size]);
1488 var user_desc: if (target.cpu.arch == .x86) linux.user_desc else void = undefined;1493 var user_desc: if (target.cpu.arch == .x86) linux.user_desc else void = undefined;
1489 if (target.cpu.arch == .x86) {1494 if (target.cpu.arch == .x86) {
1490 defer tls_ptr = @intFromPtr(&user_desc);1495 defer tls_ptr = @intFromPtr(&user_desc);
lib/std/os/linux.zig+5
...@@ -1584,6 +1584,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {...@@ -1584,6 +1584,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
1584 return syscall2(.clone, flags, child_stack_ptr);1584 return syscall2(.clone, flags, child_stack_ptr);
1585}1585}
15861586
1587/// This call cannot fail, and the return value is the caller's thread id
1588pub fn set_tid_address(tidptr: ?*pid_t) pid_t {
1589 return @intCast(@as(u32, @truncate(syscall1(.set_tid_address, @intFromPtr(tidptr)))));
1590}
1591
1587pub fn close(fd: fd_t) usize {1592pub fn close(fd: fd_t) usize {
1588 return syscall1(.close, @as(usize, @bitCast(@as(isize, fd))));1593 return syscall1(.close, @as(usize, @bitCast(@as(isize, fd))));
1589}1594}