Skip to content

Commit d7a763d

Browse files
committed
Handle FUTEX_OWNER_DIED properly
1 parent 20c7b2c commit d7a763d

File tree

16 files changed

+88
-66
lines changed

16 files changed

+88
-66
lines changed

library/std/src/sync/mutex.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,11 @@ impl<T: ?Sized> Mutex<T> {
313313
/// ```
314314
#[stable(feature = "rust1", since = "1.0.0")]
315315
pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
316-
unsafe {
317-
self.inner.lock();
318-
MutexGuard::new(self)
316+
if self.inner.lock() == sys::MutexState::Poisoned {
317+
self.poison.set();
319318
}
319+
320+
unsafe { MutexGuard::new(self) }
320321
}
321322

322323
/// Attempts to acquire this lock.

library/std/src/sync/poison.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ impl Flag {
7575
#[cfg(panic = "unwind")]
7676
self.failed.store(false, Ordering::Relaxed)
7777
}
78+
79+
#[inline]
80+
pub fn set(&self) {
81+
#[cfg(panic = "unwind")]
82+
self.failed.store(true, Ordering::Relaxed)
83+
}
7884
}
7985

8086
#[derive(Clone)]

library/std/src/sync/reentrant_lock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ impl<T: ?Sized> ReentrantLock<T> {
289289
if self.owner.contains(this_thread) {
290290
self.increment_lock_count().expect("lock count overflow in reentrant mutex");
291291
} else {
292-
self.mutex.lock();
292+
let _ = self.mutex.lock();
293293
self.owner.set(Some(this_thread));
294294
debug_assert_eq!(*self.lock_count.get(), 0);
295295
*self.lock_count.get() = 1;

library/std/src/sys/pal/unix/pi_futex.rs

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
#![cfg(any(target_os = "linux", target_os = "android"))]
22

3+
use crate::io;
4+
use crate::ptr::null;
35
use crate::sync::atomic::AtomicU32;
46
use crate::sys::cvt;
5-
use crate::sys::os::errno;
6-
use crate::{io, ptr};
7-
8-
pub enum FutexLockError {
9-
TryAgain,
10-
DeadLock,
11-
Other(io::Error),
12-
}
137

148
pub const fn unlocked() -> u32 {
159
0
@@ -23,25 +17,26 @@ pub fn is_contended(futex_val: u32) -> bool {
2317
(futex_val & libc::FUTEX_WAITERS) != 0
2418
}
2519

26-
pub fn futex_lock(futex: &AtomicU32) -> Result<(), FutexLockError> {
27-
if (unsafe {
28-
libc::syscall(
29-
libc::SYS_futex,
30-
futex as *const AtomicU32,
31-
libc::FUTEX_LOCK_PI | libc::FUTEX_PRIVATE_FLAG,
32-
0,
33-
ptr::null::<u32>(),
34-
// remaining args are unused
35-
)
36-
} == -1)
37-
{
38-
Err(match errno() {
39-
libc::EAGAIN | libc::EINTR => FutexLockError::TryAgain,
40-
libc::EDEADLK => FutexLockError::DeadLock,
41-
errno => FutexLockError::Other(io::Error::from_raw_os_error(errno)),
42-
})
43-
} else {
44-
Ok(())
20+
pub fn is_owned_died(futex_val: u32) -> bool {
21+
(futex_val & libc::FUTEX_OWNER_DIED) != 0
22+
}
23+
24+
pub fn futex_lock(futex: &AtomicU32) -> io::Result<()> {
25+
loop {
26+
match cvt(unsafe {
27+
libc::syscall(
28+
libc::SYS_futex,
29+
futex as *const AtomicU32,
30+
libc::FUTEX_LOCK_PI | libc::FUTEX_PRIVATE_FLAG,
31+
0,
32+
null::<u32>(),
33+
// remaining args are unused
34+
)
35+
}) {
36+
Ok(_) => return Ok(()),
37+
Err(e) if e.raw_os_error() == Some(libc::EINTR) => continue,
38+
Err(e) => return Err(e),
39+
}
4540
}
4641
}
4742

library/std/src/sys/sync/condvar/futex.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ impl Condvar {
5050
let r = futex_wait(&self.futex, futex_value, timeout);
5151

5252
// Lock the mutex again.
53-
mutex.lock();
53+
let _ = mutex.lock();
5454

5555
r
5656
}

library/std/src/sys/sync/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod rwlock;
66
mod thread_parking;
77

88
pub use condvar::Condvar;
9-
pub use mutex::Mutex;
9+
pub use mutex::{Mutex, MutexState};
1010
pub use once::{Once, OnceState};
1111
#[allow(unused)] // Only used on some platforms.
1212
use once_box::OnceBox;

library/std/src/sys/sync/mutex/fuchsia.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
//!
3838
//! [mutex in Fuchsia's libsync]: https://cs.opensource.google/fuchsia/fuchsia/+/main:zircon/system/ulib/sync/mutex.c
3939
40+
use super::MutexState;
4041
use crate::sync::atomic::AtomicU32;
4142
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
4243
use crate::sys::futex::zircon::{
@@ -88,7 +89,7 @@ impl Mutex {
8889
}
8990

9091
#[inline]
91-
pub fn lock(&self) {
92+
pub fn lock(&self) -> MutexState {
9293
let thread_self = unsafe { zx_thread_self() };
9394
if let Err(state) =
9495
self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed)
@@ -97,6 +98,7 @@ impl Mutex {
9798
self.lock_contested(state, thread_self);
9899
}
99100
}
101+
MutexState::Normal
100102
}
101103

102104
/// # Safety

library/std/src/sys/sync/mutex/futex.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::MutexState;
12
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
23
use crate::sys::futex::{self, futex_wait, futex_wake};
34

@@ -24,10 +25,11 @@ impl Mutex {
2425
}
2526

2627
#[inline]
27-
pub fn lock(&self) {
28+
pub fn lock(&self) -> MutexState {
2829
if self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_err() {
2930
self.lock_contended();
3031
}
32+
MutexState::Normal
3133
}
3234

3335
#[cold]

library/std/src/sys/sync/mutex/itron.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! `TA_INHERIT` are available.
33
#![forbid(unsafe_op_in_unsafe_fn)]
44

5+
use super::MutexState;
56
use crate::sys::pal::itron::abi;
67
use crate::sys::pal::itron::error::{ItronError, expect_success, expect_success_aborting, fail};
78
use crate::sys::pal::itron::spin::SpinIdOnceCell;
@@ -37,9 +38,10 @@ impl Mutex {
3738
}
3839
}
3940

40-
pub fn lock(&self) {
41+
pub fn lock(&self) -> MutexState {
4142
let mtx = self.raw();
4243
expect_success(unsafe { abi::loc_mtx(mtx) }, &"loc_mtx");
44+
MutexState::Normal
4345
}
4446

4547
pub unsafe fn unlock(&self) {

library/std/src/sys/sync/mutex/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#[derive(Copy, Clone, Eq, PartialEq)]
2+
pub enum MutexState {
3+
Normal,
4+
Poisoned,
5+
}
6+
17
cfg_if::cfg_if! {
28
if #[cfg(any(
39
target_os = "linux",

0 commit comments

Comments
 (0)