| ... | @@ -372,7 +372,10 @@ const Thread = struct { | ... | @@ -372,7 +372,10 @@ const Thread = struct { |
| 372 | }; | 372 | }; |
| 373 | }, | 373 | }, |
| 374 | else => if (std.Thread.use_pthreads) { | 374 | else => if (std.Thread.use_pthreads) { |
| 375 | return pthreads_futex.wait(ptr, expect, timeout_ns); | 375 | // TODO integrate the following function being called with robust cancelation. |
| | 376 | return pthreads_futex.wait(ptr, expect, timeout_ns) catch |err| switch (err) { |
| | 377 | error.Timeout => {}, |
| | 378 | }; |
| 376 | } else { | 379 | } else { |
| 377 | @compileError("unimplemented: futexWait"); | 380 | @compileError("unimplemented: futexWait"); |
| 378 | }, | 381 | }, |
| ... | @@ -11583,7 +11586,7 @@ const pthreads_futex = struct { | ... | @@ -11583,7 +11586,7 @@ const pthreads_futex = struct { |
| 11583 | // This can be changed with pthread_condattr_setclock, but it's an extension and may not be available everywhere. | 11586 | // This can be changed with pthread_condattr_setclock, but it's an extension and may not be available everywhere. |
| 11584 | var ts: c.timespec = undefined; | 11587 | var ts: c.timespec = undefined; |
| 11585 | if (timeout) |timeout_ns| { | 11588 | if (timeout) |timeout_ns| { |
| 11586 | ts = std.posix.clock_gettime(c.CLOCK.REALTIME) catch unreachable; | 11589 | ts = std.posix.clock_gettime(c.CLOCK.REALTIME) catch return error.Timeout; |
| 11587 | ts.sec +|= @as(@TypeOf(ts.sec), @intCast(timeout_ns / std.time.ns_per_s)); | 11590 | ts.sec +|= @as(@TypeOf(ts.sec), @intCast(timeout_ns / std.time.ns_per_s)); |
| 11588 | ts.nsec += @as(@TypeOf(ts.nsec), @intCast(timeout_ns % std.time.ns_per_s)); | 11591 | ts.nsec += @as(@TypeOf(ts.nsec), @intCast(timeout_ns % std.time.ns_per_s)); |
| 11589 | | 11592 | |
| ... | @@ -11617,9 +11620,9 @@ const pthreads_futex = struct { | ... | @@ -11617,9 +11620,9 @@ const pthreads_futex = struct { |
| 11617 | self.state = .empty; | 11620 | self.state = .empty; |
| 11618 | return error.Timeout; | 11621 | return error.Timeout; |
| 11619 | }, | 11622 | }, |
| 11620 | .INVAL => unreachable, // cond, mutex, and potentially ts should all be valid | 11623 | .INVAL => recoverableOsBugDetected(), // cond, mutex, and potentially ts should all be valid |
| 11621 | .PERM => unreachable, // mutex is locked when cond_*wait() functions are called | 11624 | .PERM => recoverableOsBugDetected(), // mutex is locked when cond_*wait() functions are called |
| 11622 | else => unreachable, | 11625 | else => recoverableOsBugDetected(), |
| 11623 | } | 11626 | } |
| 11624 | } | 11627 | } |
| 11625 | } | 11628 | } |
| ... | @@ -11866,9 +11869,12 @@ const pthreads_futex = struct { | ... | @@ -11866,9 +11869,12 @@ const pthreads_futex = struct { |
| 11866 | } | 11869 | } |
| 11867 | | 11870 | |
| 11868 | waiter.event.wait(timeout) catch { | 11871 | waiter.event.wait(timeout) catch { |
| 11869 | // If we fail to cancel after a timeout, it means a wake() thread dequeued us and will wake us up. | 11872 | // If we fail to cancel after a timeout, it means a wake() thread |
| 11870 | // We must wait until the event is set as that's a signal that the wake() thread won't access the waiter memory anymore. | 11873 | // dequeued us and will wake us up. We must wait until the event is |
| 11871 | // If we return early without waiting, the waiter on the stack would be invalidated and the wake() thread risks a UAF. | 11874 | // set as that's a signal that the wake() thread won't access the |
| | 11875 | // waiter memory anymore. If we return early without waiting, the |
| | 11876 | // waiter on the stack would be invalidated and the wake() thread |
| | 11877 | // risks a UAF. |
| 11872 | defer if (!canceled) waiter.event.wait(null) catch unreachable; | 11878 | defer if (!canceled) waiter.event.wait(null) catch unreachable; |
| 11873 | | 11879 | |
| 11874 | assert(c.pthread_mutex_lock(&bucket.mutex) == .SUCCESS); | 11880 | assert(c.pthread_mutex_lock(&bucket.mutex) == .SUCCESS); |