Skip to content

Panic backend has incompatible std::panic::panicking behavior #6

@purplesyringa

Description

@purplesyringa

On all nightly backends, the following test passes:

use lithium::{catch, throw};
use std::sync::Mutex;

let mutex = Mutex::new(());
let _ = catch::<(), ()>(|| {
    let _guard = mutex.lock();
    unsafe { throw(()) };
});

assert!(!mutex.is_poisoned());

But on the panic backend, std::panic::panicking returns true in destructors during unwinding. This is arguably reasonable behavior, but it means that in #[iex], returning errors via throwing has different mutex poisoning behavior from monadic results.

I don't see many good ways to resolve this.

  1. We could modify nightly backends to poison mutex during unwinding as well, which would be consistent, but unacceptable for #[iex].
  2. We could adjust LOCAL_COUNT by hand in the panic backend. We can't access the LOCAL_COUNT symbol directly, though, and we can't hardcode its mangled name due to hashes, so we'd have to find it in build.rs and use #[link_name]. And it's a TLS symbol, which further complicates manners, because now we'll also have to hard-code the TLS implementation; or somehow locate the corresponding symbols within build.rs again.
  3. We could also just force RUSTC_BOOTSTRAP=1 in build.rs and use nightly backends even on stable. (Setting the env var directly probably doesn't work, but we could find a suitable workaround.)

Option 3 looks bad, but honestly option 2 looks even worse, so I'm thinking that it might be the best available solution. It'll increase the likelihood of breakage, mostly due to the reliance on core::intrinsics::catch_unwind, but it's probably less fragile than playing around with symbol names.

Eugh.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions