authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-01 19:02:09-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-12-01 19:17:52-08:00
logbf0ffc45b9ca76250749097522714b7e3831a0c1
tree8cb4cc7f7a002d5282cfa23d46054ccca627d846
parent54a84964f8e3cd015688c6929612f7438b7e9553

std.Io.Threaded: musl: handle ECANCELED same as EINTR

Otherwise the pthread_cancel can affect unrelated tasks.

1 files changed, 92 insertions(+), 155 deletions(-)

lib/std/Io/Threaded.zig+92-155
......@@ -93,10 +93,10 @@ pub const Pid = if (native_os == .linux) enum(posix.pid_t) {
9393const Thread = struct {
9494 /// The value that needs to be passed to pthread_kill or tgkill in order to
9595 /// send a signal.
96 signal_id: SignalId,
96 signal_id: SignaleeId,
9797 current_closure: ?*Closure = null,
9898
99 const SignalId = if (std.Thread.use_pthreads) std.c.pthread_t else std.Thread.Id;
99 const SignaleeId = if (std.Thread.use_pthreads) std.c.pthread_t else std.Thread.Id;
100100
101101 threadlocal var current: ?*Thread = null;
102102
......@@ -113,11 +113,15 @@ const Thread = struct {
113113 .acknowledged,
114114 .acq_rel,
115115 .acquire,
116 ) orelse return error.Canceled) {
117 .none => return,
116 ) orelse {
117 if (is_musl) assert(std.c.pthread_setcancelstate(.DISABLE, null) == .SUCCESS);
118 return error.Canceled;
119 }) {
118120 .requested => unreachable,
119121 .acknowledged => unreachable,
120 _ => return,
122 .none, _ => {
123 if (is_musl) assert(std.c.pthread_setcancelstate(.MASKED, null) == .SUCCESS);
124 },
121125 }
122126 }
123127
......@@ -128,13 +132,14 @@ const Thread = struct {
128132 CancelStatus,
129133 &closure.cancel_status,
130134 .none,
131 .fromSignalId(thread.signal_id),
135 .fromSignaleeId(thread.signal_id),
132136 .acq_rel,
133137 .acquire,
134138 ) orelse return) {
135139 .none => unreachable,
136140 .requested => {
137141 @atomicStore(CancelStatus, &closure.cancel_status, .acknowledged, .release);
142 if (is_musl) assert(std.c.pthread_setcancelstate(.DISABLE, null) == .SUCCESS);
138143 return error.Canceled;
139144 },
140145 .acknowledged => return,
......@@ -144,24 +149,22 @@ const Thread = struct {
144149
145150 fn endSyscall(thread: *Thread) void {
146151 const closure = thread.current_closure orelse return;
147 _ = @cmpxchgStrong(
152 const prev = @cmpxchgStrong(
148153 CancelStatus,
149154 &closure.cancel_status,
150 .fromSignalId(thread.signal_id),
155 .fromSignaleeId(thread.signal_id),
151156 .none,
152157 .acq_rel,
153158 .acquire,
154 );
155 }
156
157 fn endSyscallCanceled(thread: *Thread) Io.Cancelable {
158 if (thread.current_closure) |closure| {
159 @atomicStore(CancelStatus, &closure.cancel_status, .acknowledged, .release);
159 ) orelse return;
160 if (is_musl and prev == .requested) {
161 // They called pthread_cancel, but we want to disarm it since
162 // the next call to beginSyscall will notice requested status.
163 assert(std.c.pthread_setcancelstate(.DISABLE, null) == .SUCCESS);
160164 }
161 return error.Canceled;
162165 }
163166
164 fn currentSignalId() SignalId {
167 fn currentSignalId() SignaleeId {
165168 return if (std.Thread.use_pthreads) std.c.pthread_self() else std.Thread.getCurrentId();
166169 }
167170};
......@@ -184,7 +187,7 @@ const CancelStatus = enum(usize) {
184187 /// Cancellation has been acknowledged and is in progress. Signals should
185188 /// not be sent.
186189 acknowledged = std.math.maxInt(usize),
187 /// Stores a `Thread.SignalId` and indicates that sending a signal to this thread
190 /// Stores a `Thread.SignaleeId` and indicates that sending a signal to this thread
188191 /// is needed in order to cancel. This state is set before going into
189192 /// a blocking operation that needs to get unblocked via signal.
190193 _,
......@@ -193,7 +196,7 @@ const CancelStatus = enum(usize) {
193196 none,
194197 requested,
195198 acknowledged,
196 signal_id: Thread.SignalId,
199 signal_id: Thread.SignaleeId,
197200 };
198201
199202 fn unpack(cs: CancelStatus) Unpacked {
......@@ -210,7 +213,7 @@ const CancelStatus = enum(usize) {
210213 };
211214 }
212215
213 fn fromSignalId(signal_id: Thread.SignalId) CancelStatus {
216 fn fromSignaleeId(signal_id: Thread.SignaleeId) CancelStatus {
214217 return if (std.Thread.use_pthreads)
215218 @enumFromInt(@intFromPtr(signal_id))
216219 else
......@@ -397,6 +400,10 @@ fn worker(t: *Threaded) void {
397400
398401 // Musl has an undocumented extension that makes pthread_cancel have the useful, desired
399402 // behavior of causing the next syscall to return ECANCELED.
403 //
404 // The call to `requestCancel` and this can race, leading to
405 // ECANCELED being returned for a syscall in an unrelated task,
406 // which is why EINTR and ECANCELED are both handled with a check.
400407 if (is_musl) assert(std.c.pthread_setcancelstate(.MASKED, null) == .SUCCESS);
401408
402409 const closure: *Closure = @fieldParentPtr("node", closure_node);
......@@ -1239,11 +1246,10 @@ fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode:
12391246 current_thread.endSyscall();
12401247 return;
12411248 },
1242 .INTR => {
1249 .INTR, .CANCELED => {
12431250 try current_thread.checkCancel();
12441251 continue;
12451252 },
1246 .CANCELED => return current_thread.endSyscallCanceled(),
12471253 else => |e| {
12481254 current_thread.endSyscall();
12491255 switch (e) {
......@@ -1282,11 +1288,10 @@ fn dirMakeWasi(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: I
12821288 current_thread.endSyscall();
12831289 return;
12841290 },
1285 .INTR => {
1291 .INTR, .CANCELED => {
12861292 try current_thread.checkCancel();
12871293 continue;
12881294 },
1289 .CANCELED => return current_thread.endSyscallCanceled(),
12901295 else => |e| {
12911296 current_thread.endSyscall();
12921297 switch (e) {
......@@ -1548,11 +1553,10 @@ fn dirStatPathLinux(
15481553 current_thread.endSyscall();
15491554 return statFromLinux(&statx);
15501555 },
1551 .INTR => {
1556 .INTR, .CANCELED => {
15521557 try current_thread.checkCancel();
15531558 continue;
15541559 },
1555 .CANCELED => return current_thread.endSyscallCanceled(),
15561560 else => |e| {
15571561 current_thread.endSyscall();
15581562 switch (e) {
......@@ -1594,11 +1598,10 @@ fn dirStatPathPosix(
15941598 current_thread.endSyscall();
15951599 return statFromPosix(&stat);
15961600 },
1597 .INTR => {
1601 .INTR, .CANCELED => {
15981602 try current_thread.checkCancel();
15991603 continue;
16001604 },
1601 .CANCELED => return current_thread.endSyscallCanceled(),
16021605 else => |e| {
16031606 current_thread.endSyscall();
16041607 switch (e) {
......@@ -1655,11 +1658,10 @@ fn dirStatPathWasi(
16551658 current_thread.endSyscall();
16561659 return statFromWasi(&stat);
16571660 },
1658 .INTR => {
1661 .INTR, .CANCELED => {
16591662 try current_thread.checkCancel();
16601663 continue;
16611664 },
1662 .CANCELED => return current_thread.endSyscallCanceled(),
16631665 else => |e| {
16641666 current_thread.endSyscall();
16651667 switch (e) {
......@@ -1701,11 +1703,10 @@ fn fileStatPosix(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File
17011703 current_thread.endSyscall();
17021704 return statFromPosix(&stat);
17031705 },
1704 .INTR => {
1706 .INTR, .CANCELED => {
17051707 try current_thread.checkCancel();
17061708 continue;
17071709 },
1708 .CANCELED => return current_thread.endSyscallCanceled(),
17091710 else => |e| {
17101711 current_thread.endSyscall();
17111712 switch (e) {
......@@ -1740,11 +1741,10 @@ fn fileStatLinux(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File
17401741 current_thread.endSyscall();
17411742 return statFromLinux(&statx);
17421743 },
1743 .INTR => {
1744 .INTR, .CANCELED => {
17441745 try current_thread.checkCancel();
17451746 continue;
17461747 },
1747 .CANCELED => return current_thread.endSyscallCanceled(),
17481748 else => |e| {
17491749 current_thread.endSyscall();
17501750 switch (e) {
......@@ -1826,11 +1826,10 @@ fn fileStatWasi(userdata: ?*anyopaque, file: Io.File) Io.File.StatError!Io.File.
18261826 current_thread.endSyscall();
18271827 return statFromWasi(&stat);
18281828 },
1829 .INTR => {
1829 .INTR, .CANCELED => {
18301830 try current_thread.checkCancel();
18311831 continue;
18321832 },
1833 .CANCELED => return current_thread.endSyscallCanceled(),
18341833 else => |e| {
18351834 current_thread.endSyscall();
18361835 switch (e) {
......@@ -1878,11 +1877,10 @@ fn dirAccessPosix(
18781877 current_thread.endSyscall();
18791878 return;
18801879 },
1881 .INTR => {
1880 .INTR, .CANCELED => {
18821881 try current_thread.checkCancel();
18831882 continue;
18841883 },
1885 .CANCELED => return current_thread.endSyscallCanceled(),
18861884 else => |e| {
18871885 current_thread.endSyscall();
18881886 switch (e) {
......@@ -1928,11 +1926,10 @@ fn dirAccessWasi(
19281926 current_thread.endSyscall();
19291927 break;
19301928 },
1931 .INTR => {
1929 .INTR, .CANCELED => {
19321930 try current_thread.checkCancel();
19331931 continue;
19341932 },
1935 .CANCELED => return current_thread.endSyscallCanceled(),
19361933 else => |e| {
19371934 current_thread.endSyscall();
19381935 switch (e) {
......@@ -2075,11 +2072,10 @@ fn dirCreateFilePosix(
20752072 current_thread.endSyscall();
20762073 break @intCast(rc);
20772074 },
2078 .INTR => {
2075 .INTR, .CANCELED => {
20792076 try current_thread.checkCancel();
20802077 continue;
20812078 },
2082 .CANCELED => return current_thread.endSyscallCanceled(),
20832079 else => |e| {
20842080 current_thread.endSyscall();
20852081 switch (e) {
......@@ -2130,11 +2126,10 @@ fn dirCreateFilePosix(
21302126 current_thread.endSyscall();
21312127 break;
21322128 },
2133 .INTR => {
2129 .INTR, .CANCELED => {
21342130 try current_thread.checkCancel();
21352131 continue;
21362132 },
2137 .CANCELED => return current_thread.endSyscallCanceled(),
21382133 else => |e| {
21392134 current_thread.endSyscall();
21402135 switch (e) {
......@@ -2159,7 +2154,7 @@ fn dirCreateFilePosix(
21592154 current_thread.endSyscall();
21602155 break @intCast(rc);
21612156 },
2162 .INTR => {
2157 .INTR, .CANCELED => {
21632158 try current_thread.checkCancel();
21642159 continue;
21652160 },
......@@ -2179,7 +2174,7 @@ fn dirCreateFilePosix(
21792174 current_thread.endSyscall();
21802175 break;
21812176 },
2182 .INTR => {
2177 .INTR, .CANCELED => {
21832178 try current_thread.checkCancel();
21842179 continue;
21852180 },
......@@ -2285,11 +2280,10 @@ fn dirCreateFileWasi(
22852280 current_thread.endSyscall();
22862281 return .{ .handle = fd };
22872282 },
2288 .INTR => {
2283 .INTR, .CANCELED => {
22892284 try current_thread.checkCancel();
22902285 continue;
22912286 },
2292 .CANCELED => return current_thread.endSyscallCanceled(),
22932287 else => |e| {
22942288 current_thread.endSyscall();
22952289 switch (e) {
......@@ -2379,11 +2373,10 @@ fn dirOpenFilePosix(
23792373 current_thread.endSyscall();
23802374 break @intCast(rc);
23812375 },
2382 .INTR => {
2376 .INTR, .CANCELED => {
23832377 try current_thread.checkCancel();
23842378 continue;
23852379 },
2386 .CANCELED => return current_thread.endSyscallCanceled(),
23872380 else => |e| {
23882381 current_thread.endSyscall();
23892382 switch (e) {
......@@ -2433,11 +2426,10 @@ fn dirOpenFilePosix(
24332426 current_thread.endSyscall();
24342427 break;
24352428 },
2436 .INTR => {
2429 .INTR, .CANCELED => {
24372430 try current_thread.checkCancel();
24382431 continue;
24392432 },
2440 .CANCELED => return current_thread.endSyscallCanceled(),
24412433 else => |e| {
24422434 current_thread.endSyscall();
24432435 switch (e) {
......@@ -2462,11 +2454,10 @@ fn dirOpenFilePosix(
24622454 current_thread.endSyscall();
24632455 break @intCast(rc);
24642456 },
2465 .INTR => {
2457 .INTR, .CANCELED => {
24662458 try current_thread.checkCancel();
24672459 continue;
24682460 },
2469 .CANCELED => return current_thread.endSyscallCanceled(),
24702461 else => |err| {
24712462 current_thread.endSyscall();
24722463 return posix.unexpectedErrno(err);
......@@ -2483,11 +2474,10 @@ fn dirOpenFilePosix(
24832474 current_thread.endSyscall();
24842475 break;
24852476 },
2486 .INTR => {
2477 .INTR, .CANCELED => {
24872478 try current_thread.checkCancel();
24882479 continue;
24892480 },
2490 .CANCELED => return current_thread.endSyscallCanceled(),
24912481 else => |err| {
24922482 current_thread.endSyscall();
24932483 return posix.unexpectedErrno(err);
......@@ -2682,11 +2672,10 @@ fn dirOpenFileWasi(
26822672 current_thread.endSyscall();
26832673 return .{ .handle = fd };
26842674 },
2685 .INTR => {
2675 .INTR, .CANCELED => {
26862676 try current_thread.checkCancel();
26872677 continue;
26882678 },
2689 .CANCELED => return current_thread.endSyscallCanceled(),
26902679 else => |e| {
26912680 current_thread.endSyscall();
26922681 switch (e) {
......@@ -2766,11 +2755,10 @@ fn dirOpenDirPosix(
27662755 current_thread.endSyscall();
27672756 return .{ .handle = @intCast(rc) };
27682757 },
2769 .INTR => {
2758 .INTR, .CANCELED => {
27702759 try current_thread.checkCancel();
27712760 continue;
27722761 },
2773 .CANCELED => return current_thread.endSyscallCanceled(),
27742762 else => |e| {
27752763 current_thread.endSyscall();
27762764 switch (e) {
......@@ -2819,11 +2807,10 @@ fn dirOpenDirHaiku(
28192807 return .{ .handle = rc };
28202808 }
28212809 switch (@as(posix.E, @enumFromInt(rc))) {
2822 .INTR => {
2810 .INTR, .CANCELED => {
28232811 try current_thread.checkCancel();
28242812 continue;
28252813 },
2826 .CANCELED => return current_thread.endSyscallCanceled(),
28272814 else => |e| {
28282815 current_thread.endSyscall();
28292816 switch (e) {
......@@ -2964,11 +2951,10 @@ fn dirOpenDirWasi(
29642951 current_thread.endSyscall();
29652952 return .{ .handle = fd };
29662953 },
2967 .INTR => {
2954 .INTR, .CANCELED => {
29682955 try current_thread.checkCancel();
29692956 continue;
29702957 },
2971 .CANCELED => return current_thread.endSyscallCanceled(),
29722958 else => |e| {
29732959 current_thread.endSyscall();
29742960 switch (e) {
......@@ -3031,11 +3017,10 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io
30313017 current_thread.endSyscall();
30323018 return nread;
30333019 },
3034 .INTR => {
3020 .INTR, .CANCELED => {
30353021 try current_thread.checkCancel();
30363022 continue;
30373023 },
3038 .CANCELED => return current_thread.endSyscallCanceled(),
30393024 else => |e| {
30403025 current_thread.endSyscall();
30413026 switch (e) {
......@@ -3065,11 +3050,10 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8) Io
30653050 current_thread.endSyscall();
30663051 return @intCast(rc);
30673052 },
3068 .INTR => {
3053 .INTR, .CANCELED => {
30693054 try current_thread.checkCancel();
30703055 continue;
30713056 },
3072 .CANCELED => return current_thread.endSyscallCanceled(),
30733057 else => |e| {
30743058 current_thread.endSyscall();
30753059 switch (e) {
......@@ -3151,11 +3135,10 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o
31513135 current_thread.endSyscall();
31523136 return nread;
31533137 },
3154 .INTR => {
3138 .INTR, .CANCELED => {
31553139 try current_thread.checkCancel();
31563140 continue;
31573141 },
3158 .CANCELED => return current_thread.endSyscallCanceled(),
31593142 else => |e| {
31603143 current_thread.endSyscall();
31613144 switch (e) {
......@@ -3189,11 +3172,10 @@ fn fileReadPositionalPosix(userdata: ?*anyopaque, file: Io.File, data: [][]u8, o
31893172 current_thread.endSyscall();
31903173 return @bitCast(rc);
31913174 },
3192 .INTR => {
3175 .INTR, .CANCELED => {
31933176 try current_thread.checkCancel();
31943177 continue;
31953178 },
3196 .CANCELED => return current_thread.endSyscallCanceled(),
31973179 else => |e| {
31983180 current_thread.endSyscall();
31993181 switch (e) {
......@@ -3291,11 +3273,10 @@ fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekErr
32913273 current_thread.endSyscall();
32923274 return;
32933275 },
3294 .INTR => {
3276 .INTR, .CANCELED => {
32953277 try current_thread.checkCancel();
32963278 continue;
32973279 },
3298 .CANCELED => return current_thread.endSyscallCanceled(),
32993280 else => |e| {
33003281 current_thread.endSyscall();
33013282 switch (e) {
......@@ -3324,11 +3305,10 @@ fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekErr
33243305 current_thread.endSyscall();
33253306 return;
33263307 },
3327 .INTR => {
3308 .INTR, .CANCELED => {
33283309 try current_thread.checkCancel();
33293310 continue;
33303311 },
3331 .CANCELED => return current_thread.endSyscallCanceled(),
33323312 else => |e| {
33333313 current_thread.endSyscall();
33343314 switch (e) {
......@@ -3353,11 +3333,10 @@ fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekErr
33533333 current_thread.endSyscall();
33543334 return;
33553335 },
3356 .INTR => {
3336 .INTR, .CANCELED => {
33573337 try current_thread.checkCancel();
33583338 continue;
33593339 },
3360 .CANCELED => return current_thread.endSyscallCanceled(),
33613340 else => |e| {
33623341 current_thread.endSyscall();
33633342 switch (e) {
......@@ -3510,11 +3489,10 @@ fn sleepLinux(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
35103489 current_thread.endSyscall();
35113490 return;
35123491 },
3513 .INTR => {
3492 .INTR, .CANCELED => {
35143493 try current_thread.checkCancel();
35153494 continue;
35163495 },
3517 .CANCELED => return current_thread.endSyscallCanceled(),
35183496 else => |e| {
35193497 current_thread.endSyscall();
35203498 switch (e) {
......@@ -3588,11 +3566,10 @@ fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void {
35883566 try current_thread.beginSyscall();
35893567 while (true) {
35903568 switch (posix.errno(posix.system.nanosleep(&timespec, &timespec))) {
3591 .INTR => {
3569 .INTR, .CANCELED => {
35923570 try current_thread.checkCancel();
35933571 continue;
35943572 },
3595 .CANCELED => return current_thread.endSyscallCanceled(),
35963573 // This prong handles success as well as unexpected errors.
35973574 else => return current_thread.endSyscall(),
35983575 }
......@@ -3662,11 +3639,10 @@ fn netListenIpPosix(
36623639 current_thread.endSyscall();
36633640 break;
36643641 },
3665 .INTR => {
3642 .INTR, .CANCELED => {
36663643 try current_thread.checkCancel();
36673644 continue;
36683645 },
3669 .CANCELED => return current_thread.endSyscallCanceled(),
36703646 else => |e| {
36713647 current_thread.endSyscall();
36723648 switch (e) {
......@@ -3711,7 +3687,10 @@ fn netListenIpWindows(
37113687 try current_thread.beginSyscall();
37123688 while (true) {
37133689 const rc = ws2_32.bind(socket_handle, &storage.any, addr_len);
3714 if (rc != ws2_32.SOCKET_ERROR) break;
3690 if (rc != ws2_32.SOCKET_ERROR) {
3691 current_thread.endSyscall();
3692 break;
3693 }
37153694 switch (ws2_32.WSAGetLastError()) {
37163695 .EINTR => {
37173696 try current_thread.checkCancel();
......@@ -3739,7 +3718,7 @@ fn netListenIpWindows(
37393718 }
37403719 }
37413720
3742 try current_thread.checkCancel();
3721 try current_thread.beginSyscall();
37433722 while (true) {
37443723 const rc = ws2_32.listen(socket_handle, options.kernel_backlog);
37453724 if (rc != ws2_32.SOCKET_ERROR) {
......@@ -3823,11 +3802,10 @@ fn netListenUnixPosix(
38233802 current_thread.endSyscall();
38243803 break;
38253804 },
3826 .INTR => {
3805 .INTR, .CANCELED => {
38273806 try current_thread.checkCancel();
38283807 continue;
38293808 },
3830 .CANCELED => return current_thread.endSyscallCanceled(),
38313809 else => |e| {
38323810 current_thread.endSyscall();
38333811 switch (e) {
......@@ -3947,11 +3925,10 @@ fn posixBindUnix(
39473925 current_thread.endSyscall();
39483926 break;
39493927 },
3950 .INTR => {
3928 .INTR, .CANCELED => {
39513929 try current_thread.checkCancel();
39523930 continue;
39533931 },
3954 .CANCELED => return current_thread.endSyscallCanceled(),
39553932 else => |e| {
39563933 current_thread.endSyscall();
39573934 switch (e) {
......@@ -3992,11 +3969,10 @@ fn posixBind(
39923969 current_thread.endSyscall();
39933970 break;
39943971 },
3995 .INTR => {
3972 .INTR, .CANCELED => {
39963973 try current_thread.checkCancel();
39973974 continue;
39983975 },
3999 .CANCELED => return current_thread.endSyscallCanceled(),
40003976 else => |e| {
40013977 current_thread.endSyscall();
40023978 switch (e) {
......@@ -4028,11 +4004,10 @@ fn posixConnect(
40284004 current_thread.endSyscall();
40294005 return;
40304006 },
4031 .INTR => {
4007 .INTR, .CANCELED => {
40324008 try current_thread.checkCancel();
40334009 continue;
40344010 },
4035 .CANCELED => return current_thread.endSyscallCanceled(),
40364011 else => |e| {
40374012 current_thread.endSyscall();
40384013 switch (e) {
......@@ -4075,11 +4050,10 @@ fn posixConnectUnix(
40754050 current_thread.endSyscall();
40764051 return;
40774052 },
4078 .INTR => {
4053 .INTR, .CANCELED => {
40794054 try current_thread.checkCancel();
40804055 continue;
40814056 },
4082 .CANCELED => return current_thread.endSyscallCanceled(),
40834057 else => |e| {
40844058 current_thread.endSyscall();
40854059 switch (e) {
......@@ -4120,11 +4094,10 @@ fn posixGetSockName(
41204094 current_thread.endSyscall();
41214095 break;
41224096 },
4123 .INTR => {
4097 .INTR, .CANCELED => {
41244098 try current_thread.checkCancel();
41254099 continue;
41264100 },
4127 .CANCELED => return current_thread.endSyscallCanceled(),
41284101 else => |e| {
41294102 current_thread.endSyscall();
41304103 switch (e) {
......@@ -4188,11 +4161,10 @@ fn setSocketOption(current_thread: *Thread, fd: posix.fd_t, level: i32, opt_name
41884161 current_thread.endSyscall();
41894162 return;
41904163 },
4191 .INTR => {
4164 .INTR, .CANCELED => {
41924165 try current_thread.checkCancel();
41934166 continue;
41944167 },
4195 .CANCELED => return current_thread.endSyscallCanceled(),
41964168 else => |e| {
41974169 current_thread.endSyscall();
41984170 switch (e) {
......@@ -4521,8 +4493,7 @@ fn openSocketPosix(
45214493 try current_thread.checkCancel();
45224494 switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) {
45234495 .SUCCESS => break,
4524 .INTR => continue,
4525 .CANCELED => return current_thread.endSyscallCanceled(),
4496 .INTR, .CANCELED => continue,
45264497 else => |err| {
45274498 current_thread.endSyscall();
45284499 return posix.unexpectedErrno(err);
......@@ -4532,11 +4503,10 @@ fn openSocketPosix(
45324503 current_thread.endSyscall();
45334504 break fd;
45344505 },
4535 .INTR => {
4506 .INTR, .CANCELED => {
45364507 try current_thread.checkCancel();
45374508 continue;
45384509 },
4539 .CANCELED => return current_thread.endSyscallCanceled(),
45404510 else => |e| {
45414511 current_thread.endSyscall();
45424512 switch (e) {
......@@ -4624,7 +4594,7 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve
46244594 try current_thread.checkCancel();
46254595 switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) {
46264596 .SUCCESS => break,
4627 .INTR => continue,
4597 .INTR, .CANCELED => continue,
46284598 else => |err| {
46294599 current_thread.endSyscall();
46304600 return posix.unexpectedErrno(err);
......@@ -4634,11 +4604,10 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve
46344604 current_thread.endSyscall();
46354605 break fd;
46364606 },
4637 .INTR => {
4607 .INTR, .CANCELED => {
46384608 try current_thread.checkCancel();
46394609 continue;
46404610 },
4641 .CANCELED => return current_thread.endSyscallCanceled(),
46424611 else => |e| {
46434612 current_thread.endSyscall();
46444613 switch (e) {
......@@ -4743,11 +4712,10 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
47434712 current_thread.endSyscall();
47444713 return n;
47454714 },
4746 .INTR => {
4715 .INTR, .CANCELED => {
47474716 try current_thread.checkCancel();
47484717 continue;
47494718 },
4750 .CANCELED => return current_thread.endSyscallCanceled(),
47514719 else => |e| {
47524720 current_thread.endSyscall();
47534721 switch (e) {
......@@ -4776,11 +4744,10 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
47764744 current_thread.endSyscall();
47774745 return @intCast(rc);
47784746 },
4779 .INTR => {
4747 .INTR, .CANCELED => {
47804748 try current_thread.checkCancel();
47814749 continue;
47824750 },
4783 .CANCELED => return current_thread.endSyscallCanceled(),
47844751 else => |e| {
47854752 current_thread.endSyscall();
47864753 switch (e) {
......@@ -5012,11 +4979,10 @@ fn netSendOne(
50124979 message.data_len = @intCast(rc);
50134980 return;
50144981 },
5015 .INTR => {
4982 .INTR, .CANCELED => {
50164983 try current_thread.checkCancel();
50174984 continue;
50184985 },
5019 .CANCELED => return current_thread.endSyscallCanceled(),
50204986 else => |e| {
50214987 current_thread.endSyscall();
50224988 switch (e) {
......@@ -5089,11 +5055,10 @@ fn netSendMany(
50895055 }
50905056 return n;
50915057 },
5092 .INTR => {
5058 .INTR, .CANCELED => {
50935059 try current_thread.checkCancel();
50945060 continue;
50955061 },
5096 .CANCELED => return current_thread.endSyscallCanceled(),
50975062 else => |e| {
50985063 current_thread.endSyscall();
50995064 switch (e) {
......@@ -5225,8 +5190,7 @@ fn netReceivePosix(
52255190 }
52265191 continue :recv;
52275192 },
5228 .INTR => continue,
5229 .CANCELED => return .{ current_thread.endSyscallCanceled(), message_i },
5193 .INTR, .CANCELED => continue,
52305194
52315195 .FAULT => |err| return .{ errnoBug(err), message_i },
52325196 .INVAL => |err| return .{ errnoBug(err), message_i },
......@@ -5234,8 +5198,7 @@ fn netReceivePosix(
52345198 else => |err| return .{ posix.unexpectedErrno(err), message_i },
52355199 }
52365200 },
5237 .INTR => continue,
5238 .CANCELED => return .{ current_thread.endSyscallCanceled(), message_i },
5201 .INTR, .CANCELED => continue,
52395202
52405203 .BADF => |err| return .{ errnoBug(err), message_i },
52415204 .NFILE => return .{ error.SystemFdQuotaExceeded, message_i },
......@@ -5350,11 +5313,10 @@ fn netWritePosix(
53505313 current_thread.endSyscall();
53515314 return @intCast(rc);
53525315 },
5353 .INTR => {
5316 .INTR, .CANCELED => {
53545317 try current_thread.checkCancel();
53555318 continue;
53565319 },
5357 .CANCELED => return current_thread.endSyscallCanceled(),
53585320 else => |e| {
53595321 current_thread.endSyscall();
53605322 switch (e) {
......@@ -5452,8 +5414,7 @@ fn netWriteWindows(
54525414 else => |err| err,
54535415 };
54545416 switch (wsa_error) {
5455 .EINTR => continue,
5456 .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => return current_thread.endSyscallCanceled(),
5417 .EINTR, .ECANCELLED, .E_CANCELLED, .OPERATION_ABORTED => continue,
54575418 .NOTINITIALISED => {
54585419 try initializeWsa(t);
54595420 continue;
......@@ -5561,11 +5522,10 @@ fn netInterfaceNameResolve(
55615522 current_thread.endSyscall();
55625523 return .{ .index = @bitCast(ifr.ifru.ivalue) };
55635524 },
5564 .INTR => {
5525 .INTR, .CANCELED => {
55655526 try current_thread.checkCancel();
55665527 continue;
55675528 },
5568 .CANCELED => return current_thread.endSyscallCanceled(),
55695529 else => |e| {
55705530 current_thread.endSyscall();
55715531 switch (e) {
......@@ -5862,11 +5822,10 @@ fn netLookupFallible(
58625822 break;
58635823 },
58645824 .SYSTEM => switch (posix.errno(-1)) {
5865 .INTR => {
5825 .INTR, .CANCELED => {
58665826 try current_thread.checkCancel();
58675827 continue;
58685828 },
5869 .CANCELED => return current_thread.endSyscallCanceled(),
58705829 else => |e| {
58715830 current_thread.endSyscall();
58725831 return posix.unexpectedErrno(e);
......@@ -6612,15 +6571,15 @@ fn futexWait(current_thread: *Thread, ptr: *const std.atomic.Value(u32), expect:
66126571 try current_thread.beginSyscall();
66136572 const rc = linux.futex_4arg(ptr, .{ .cmd = .WAIT, .private = true }, expect, null);
66146573 current_thread.endSyscall();
6615 if (is_debug) switch (linux.errno(rc)) {
6574 switch (linux.errno(rc)) {
66166575 .SUCCESS => {}, // notified by `wake()`
6617 .INTR => {}, // gives caller a chance to check cancellation
6576 .INTR => {}, // caller's responsibility to retry
66186577 .AGAIN => {}, // ptr.* != expect
66196578 .INVAL => {}, // possibly timeout overflow
6620 .TIMEDOUT => unreachable,
6621 .FAULT => unreachable, // ptr was invalid
6622 else => unreachable,
6623 };
6579 .TIMEDOUT => recoverableOsBugDetected(),
6580 .FAULT => recoverableOsBugDetected(), // ptr was invalid
6581 else => recoverableOsBugDetected(),
6582 }
66246583 },
66256584 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => {
66266585 const c = std.c;
......@@ -6703,7 +6662,7 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi
67036662 const rc = linux.futex_4arg(ptr, .{ .cmd = .WAIT, .private = true }, expect, null);
67046663 switch (linux.errno(rc)) {
67056664 .SUCCESS => {}, // notified by `wake()`
6706 .INTR => {}, // gives caller a chance to check cancellation
6665 .INTR => {}, // caller's responsibility to repeat
67076666 .AGAIN => {}, // ptr.* != expect
67086667 .INVAL => {}, // possibly timeout overflow
67096668 .TIMEDOUT => recoverableOsBugDetected(),
......@@ -6757,28 +6716,6 @@ pub fn futexWaitUncancelable(ptr: *const std.atomic.Value(u32), expect: u32) voi
67576716 }
67586717}
67596718
6760pub fn futexWaitDurationUncancelable(ptr: *const std.atomic.Value(u32), expect: u32, timeout: Io.Duration) void {
6761 @branchHint(.cold);
6762
6763 if (native_os == .linux) {
6764 const linux = std.os.linux;
6765 var ts = timestampToPosix(timeout.toNanoseconds());
6766 const rc = linux.futex_4arg(ptr, .{ .cmd = .WAIT, .private = true }, expect, &ts);
6767 if (is_debug) switch (linux.errno(rc)) {
6768 .SUCCESS => {}, // notified by `wake()`
6769 .INTR => {}, // gives caller a chance to check cancellation
6770 .AGAIN => {}, // ptr.* != expect
6771 .TIMEDOUT => {},
6772 .INVAL => {}, // possibly timeout overflow
6773 .FAULT => unreachable, // ptr was invalid
6774 else => unreachable,
6775 };
6776 return;
6777 } else {
6778 @compileError("TODO");
6779 }
6780}
6781
67826719pub fn futexWake(ptr: *const std.atomic.Value(u32), max_waiters: u32) void {
67836720 @branchHint(.cold);
67846721