Skip to content

Condvar isn't RefUnwindSafe when building on Mac #118009

Closed
@ecton

Description

@ecton
use std::sync::{Condvar, Mutex};
fn panic_catcher() {
    let condvar = Condvar::new();
    std::panic::catch_unwind(move || {
        let mutex = Mutex::new(());
        let guard = mutex.lock().unwrap();
        condvar.wait(guard);
    });
}

I expected to see this happen: No errors. This code compiles on Linux, as I would expect based on Condvar's documentation.

Instead, this happened: When compiling on Mac OS, I get this error:

error[E0277]: the type `UnsafeCell<libc::unix::bsd::apple::pthread_cond_t>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    --> src/lib.rs:176:30
     |
176  |       std::panic::catch_unwind(move || {
     |  _____------------------------_^
     | |     |
     | |     required by a bound introduced by this call
177  | |         let mutex = Mutex::new(());
178  | |         let guard = mutex.lock().unwrap();
179  | |         condvar.wait(guard);
180  | |     });
     | |_____^ `UnsafeCell<libc::unix::bsd::apple::pthread_cond_t>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
     |
     = help: within `std::sys::unix::locks::pthread_condvar::AllocatedCondvar`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<libc::unix::bsd::apple::pthread_cond_t>`
note: required because it appears within the type `AllocatedCondvar`
    --> /Users/ecton/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/sys/unix/locks/pthread_condvar.rs:12:8
     |
12   | struct AllocatedCondvar(UnsafeCell<libc::pthread_cond_t>);
     |        ^^^^^^^^^^^^^^^^
     = note: required for `*mut std::sys::unix::locks::pthread_condvar::AllocatedCondvar` to implement `UnwindSafe`
note: required because it appears within the type `UnsafeCell<*mut AllocatedCondvar>`
    --> /Users/ecton/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/cell.rs:1987:12
     |
1987 | pub struct UnsafeCell<T: ?Sized> {
     |            ^^^^^^^^^^
note: required because it appears within the type `AtomicPtr<AllocatedCondvar>`
    --> /Users/ecton/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/core/src/sync/atomic.rs:186:12
     |
186  | pub struct AtomicPtr<T> {
     |            ^^^^^^^^^
note: required because it appears within the type `LazyBox<AllocatedCondvar>`
    --> /Users/ecton/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/sys_common/lazy_box.rs:13:19
     |
13   | pub(crate) struct LazyBox<T: LazyInit> {
     |                   ^^^^^^^
note: required because it appears within the type `Condvar`
    --> /Users/ecton/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/sys/unix/locks/pthread_condvar.rs:14:12
     |
14   | pub struct Condvar {
     |            ^^^^^^^
note: required because it appears within the type `Condvar`
    --> /Users/ecton/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/sync/condvar.rs:107:12
     |
107  | pub struct Condvar {
     |            ^^^^^^^
note: required because it's used within this closure
    --> src/lib.rs:176:30
     |
176  |     std::panic::catch_unwind(move || {
     |                              ^^^^^^^
note: required by a bound in `catch_unwind`
    --> /Users/ecton/.rustup/toolchains/stable-aarch64-apple-darwin/lib/rustlib/src/rust/library/std/src/panic.rs:141:40
     |
141  | pub fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
     |                                        ^^^^^^^^^^ required by this bound in `catch_unwind`

On Linux, this code compiles correctly, and the hosted Rust docs for Convdar document this type as UnwindSafe. I'm filing this issue to ask:

Is the current MacOS implementation not actually UnwindSafe? My workaround for this issue is to wrap Condvar in AssertUnwindwSafe, but I would like to confirm this is actually safe. My personal hope is that these sync primitives are UnwindSafe and that this is a safe workaround.

Meta

rustc --version --verbose:

rustc 1.74.0 (79e9716c9 2023-11-13)
binary: rustc
commit-hash: 79e9716c980570bfd1f666e3b16ac583f0168962
commit-date: 2023-11-13
host: x86_64-unknown-linux-gnu
release: 1.74.0
LLVM version: 17.0.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.O-macosOperating system: macOST-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions