about summary refs log tree commit diff
path: root/library/std/src/sys/unix
diff options
context:
space:
mode:
authorjoboet <jonasboettiger@icloud.com>2022-07-12 12:25:43 +0200
committerjoboet <jonasboettiger@icloud.com>2022-07-12 12:25:43 +0200
commit0d91b08970301ae586031b1b2437a44115074efc (patch)
tree493de6109c59ce716b3bffe4aef2f8604ef99613 /library/std/src/sys/unix
parentf7ae92c6bd9b50e3d1cd7ce123ffa15d0e1ecd97 (diff)
downloadrust-0d91b08970301ae586031b1b2437a44115074efc.tar.gz
rust-0d91b08970301ae586031b1b2437a44115074efc.zip
std: fix issue with perma-locked mutexes on Fuchsia
Diffstat (limited to 'library/std/src/sys/unix')
-rw-r--r--library/std/src/sys/unix/futex.rs4
-rw-r--r--library/std/src/sys/unix/locks/fuchsia_mutex.rs25
2 files changed, 20 insertions, 9 deletions
diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs
index 9480451fc5c..96b07b510a7 100644
--- a/library/std/src/sys/unix/futex.rs
+++ b/library/std/src/sys/unix/futex.rs
@@ -251,6 +251,9 @@ pub mod zircon {
     pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX;
 
     pub const ZX_OK: zx_status_t = 0;
+    pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10;
+    pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11;
+    pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12;
     pub const ZX_ERR_BAD_STATE: zx_status_t = -20;
     pub const ZX_ERR_TIMED_OUT: zx_status_t = -21;
 
@@ -264,6 +267,7 @@ pub mod zircon {
         ) -> zx_status_t;
         pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t;
         pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t;
+        pub fn zx_nanosleep(deadline: zx_time_t) -> zx_status_t;
         pub fn zx_thread_self() -> zx_handle_t;
     }
 }
diff --git a/library/std/src/sys/unix/locks/fuchsia_mutex.rs b/library/std/src/sys/unix/locks/fuchsia_mutex.rs
index 412e7e0018b..65d7c4eefd9 100644
--- a/library/std/src/sys/unix/locks/fuchsia_mutex.rs
+++ b/library/std/src/sys/unix/locks/fuchsia_mutex.rs
@@ -42,8 +42,9 @@ use crate::sync::atomic::{
     Ordering::{Acquire, Relaxed, Release},
 };
 use crate::sys::futex::zircon::{
-    zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t, zx_thread_self, ZX_ERR_BAD_STATE,
-    ZX_OK, ZX_TIME_INFINITE,
+    zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t, zx_nanosleep, zx_thread_self,
+    ZX_ERR_BAD_HANDLE, ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE,
+    ZX_OK, ZX_TIME_INFINITE, ZX_TIME_INFINITE,
 };
 
 // The lowest two bits of a `zx_handle_t` are always set, so the lowest bit is used to mark the
@@ -120,13 +121,19 @@ impl Mutex {
                         to_owner(state),
                         ZX_TIME_INFINITE,
                     ) {
-                        ZX_OK | ZX_ERR_BAD_STATE => (),
-                        // Deadlock even in the case of reentrant locking, as leaking a guard
-                        // could lead to the same condition if the thread id is reused, but
-                        // panicking is not expected in that situation. This makes things
-                        // quite a bit harder to debug, but encourages portable programming.
-                        _ if to_owner(state) == thread_self => loop {},
-                        error => panic!("futex operation failed with error code {error}"),
+                        ZX_OK | ZX_ERR_BAD_STATE | ZX_ERR_TIMED_OUT => (),
+                        // Either the current thread is trying to lock a mutex it has already locked,
+                        // or the previous owner did not unlock the mutex before exiting. Since it is
+                        // not possible to reliably detect which is the case, the current thread is
+                        // deadlocked. This makes debugging these cases quite a bit harder, but encourages
+                        // portable programming, since all other platforms do the same.
+                        //
+                        // Note that if the thread handle is reused, an arbitrary thread's priority could
+                        // be boosted by the wait, but there is currently no way to prevent that.
+                        ZX_ERR_INVALID_ARGS | ZX_ERR_BAD_HANDLE | ZX_ERR_WRONG_TYPE => loop {
+                            zx_nanosleep(ZX_TIME_INFINITE);
+                        },
+                        error => unreachable!("unexpected error code in futex wait: {error}"),
                     }
                 }
             }