rustc: Tweak funclet cleanups of ffi functions by alexcrichton · Pull Request #48572 · rust-lang/rust (original) (raw)
This specific PR only affects Windows, not POSIX platforms. Admittedly, there might be yet another case where on Windows unwinding is used and, unlike longjmp
, is caught by catch(...)
, but we are not currently aware of any. pthread_cancel
is not something supported by Windows, and such is of no concern.
On POSIX, meanwhile, code like one below, is and always was undefined Rust (ignore all the bad bindings and stuff, it is something I prototyped quickly to demonstrate the point):
use std::os::unix::thread::*;
extern "C" { pub fn pthread_cancel(h: RawPthread) -> i32; pub fn pthread_create(t: *mut RawPthread, a: *mut (), t: extern "C" fn(*const ()) -> *const (), b: *mut ()) -> i32; }
extern "C" fn banana(x: *const ()) -> *const () { ::std::thread::sleep(::std::time::Duration::from_millis(500)); // might unwind due to pthread_cancel and is UB x }
fn main() { unsafe { let mut t: RawPthread = ::std::mem::zeroed(); pthread_create(&mut t, ::std::ptr::null_mut(), banana, ::std::ptr::null_mut()); pthread_cancel(t); } ::std::thread::sleep(::std::time::Duration::from_millis(1000)); }
Currently, the safety implemented in #46833 is disabled, so this code will silently work (it does not work when the safety net is re-enabled), however, to really make sure this code is not undefined, you need to specify the #[unwind]
attribute on top of banana
, as such:
#[unwind]
extern "C" fn banana(x: *const ()) -> *const () {
::std::thread::sleep(::std::time::Duration::from_millis(500)); // might unwind due to pthread_cancel and is not UB anymore, because banana
is specified to unwind.
x
}
This is exactly the same rule, that applies to any extern "C"
function that might unwind for any reason.