Skip to content

Commit b09ef11

Browse files
authored
Rollup merge of #77761 - tmiasko:pthread-mutex, r=cuviper
Assert that pthread mutex initialization succeeded If pthread mutex initialization fails, the failure will go unnoticed unless debug assertions are enabled. Any subsequent use of mutex will also silently fail, since return values from lock & unlock operations are similarly checked only through debug assertions. In some implementations the mutex initialization requires a memory allocation and so it does fail in practice. Assert that initialization succeeds to ensure that mutex guarantees mutual exclusion. Fixes #34966.
2 parents c5b0a88 + 21c29b1 commit b09ef11

File tree

3 files changed

+27
-22
lines changed

3 files changed

+27
-22
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ where
220220
}
221221
}
222222

223+
pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
224+
if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) }
225+
}
226+
223227
// On Unix-like platforms, libc::abort will unregister signal handlers
224228
// including the SIGABRT handler, preventing the abort from being blocked, and
225229
// fclose streams, with the side effect of flushing them so libc buffered

library/std/src/sys/unix/mutex.rs

+22-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::cell::UnsafeCell;
22
use crate::mem::MaybeUninit;
3+
use crate::sys::cvt_nz;
34

45
pub struct Mutex {
56
inner: UnsafeCell<libc::pthread_mutex_t>,
@@ -51,14 +52,11 @@ impl Mutex {
5152
// PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
5253
// re-lock it from the same thread, thus avoiding undefined behavior.
5354
let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
54-
let r = libc::pthread_mutexattr_init(attr.as_mut_ptr());
55-
debug_assert_eq!(r, 0);
56-
let r = libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL);
57-
debug_assert_eq!(r, 0);
58-
let r = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
59-
debug_assert_eq!(r, 0);
60-
let r = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
61-
debug_assert_eq!(r, 0);
55+
cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
56+
let attr = PthreadMutexAttr(&mut attr);
57+
cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL))
58+
.unwrap();
59+
cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
6260
}
6361
#[inline]
6462
pub unsafe fn lock(&self) {
@@ -106,15 +104,11 @@ impl ReentrantMutex {
106104

107105
pub unsafe fn init(&self) {
108106
let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
109-
let result = libc::pthread_mutexattr_init(attr.as_mut_ptr());
110-
debug_assert_eq!(result, 0);
111-
let result =
112-
libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE);
113-
debug_assert_eq!(result, 0);
114-
let result = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
115-
debug_assert_eq!(result, 0);
116-
let result = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
117-
debug_assert_eq!(result, 0);
107+
cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap();
108+
let attr = PthreadMutexAttr(&mut attr);
109+
cvt_nz(libc::pthread_mutexattr_settype(attr.0.as_mut_ptr(), libc::PTHREAD_MUTEX_RECURSIVE))
110+
.unwrap();
111+
cvt_nz(libc::pthread_mutex_init(self.inner.get(), attr.0.as_ptr())).unwrap();
118112
}
119113

120114
pub unsafe fn lock(&self) {
@@ -137,3 +131,14 @@ impl ReentrantMutex {
137131
debug_assert_eq!(result, 0);
138132
}
139133
}
134+
135+
struct PthreadMutexAttr<'a>(&'a mut MaybeUninit<libc::pthread_mutexattr_t>);
136+
137+
impl Drop for PthreadMutexAttr<'_> {
138+
fn drop(&mut self) {
139+
unsafe {
140+
let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr());
141+
debug_assert_eq!(result, 0);
142+
}
143+
}
144+
}

library/std/src/sys/unix/process/process_unix.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl Command {
281281
envp: Option<&CStringArray>,
282282
) -> io::Result<Option<Process>> {
283283
use crate::mem::MaybeUninit;
284-
use crate::sys;
284+
use crate::sys::{self, cvt_nz};
285285

286286
if self.get_gid().is_some()
287287
|| self.get_uid().is_some()
@@ -343,10 +343,6 @@ impl Command {
343343
}
344344
}
345345

346-
fn cvt_nz(error: libc::c_int) -> io::Result<()> {
347-
if error == 0 { Ok(()) } else { Err(io::Error::from_raw_os_error(error)) }
348-
}
349-
350346
unsafe {
351347
let mut attrs = MaybeUninit::uninit();
352348
cvt_nz(libc::posix_spawnattr_init(attrs.as_mut_ptr()))?;

0 commit comments

Comments
 (0)