Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the C-unwind ABI instead of C when mocking extern C functions #585

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ common: &COMMON
task:
name: MSRV
container:
image: rust:1.70.0
image: rust:1.71.0
cargo_lock_script:
- cp Cargo.lock.msrv Cargo.lock
<< : *COMMON
Expand Down
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- Raised MSRV to 1.70.0 to remove `lazy_static` dependency
([#550](https://github.com/asomers/mockall/pull/550))
- Raised MSRV to 1.71.0 due to the `C-unwind` ABI.
([#585](https://github.com/asomers/mockall/pull/585))

- No longer poison a Context object's internal `Mutex` when panicing. This
requires the "nightly" feature.
([#527](https://github.com/asomers/mockall/pull/527))

### Fixed

- Fixed panicing within mocked `extern "C"` functions, for example due to
unsatisfied expectations, with Rust 1.81.0 or newer.
([#585](https://github.com/asomers/mockall/pull/585))

## [ 0.12.1 ] - 2023-12-21

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ See the [API docs](https://docs.rs/mockall) for more information.

# Minimum Supported Rust Version (MSRV)

Mockall is supported on Rust 1.70.0 and higher. Mockall's MSRV will not be
Mockall is supported on Rust 1.71.0 and higher. Mockall's MSRV will not be
changed in the future without bumping the major or minor version.

# License
Expand Down
2 changes: 1 addition & 1 deletion mockall/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ categories = ["development-tools::testing"]
keywords = ["mock", "mocking", "testing"]
documentation = "https://docs.rs/mockall"
edition = "2021"
rust-version = "1.70"
rust-version = "1.71"
description = """
A powerful mock object library for Rust.
"""
Expand Down
2 changes: 1 addition & 1 deletion mockall/tests/automock_foreign_c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ fn c_abi() {
let _m = FOO_MTX.lock();
let ctx = mock_ffi::foo_context();
ctx.expect().returning(i64::from);
let p: unsafe extern "C" fn(u32) -> i64 = mock_ffi::foo;
let p: unsafe extern "C-unwind" fn(u32) -> i64 = mock_ffi::foo;
assert_eq!(42, unsafe{p(42)});
}
13 changes: 13 additions & 0 deletions mockall/tests/automock_foreign_c_variadic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,24 @@ pub mod ffi {
}
}

#[cfg(feature = "nightly")]
static FOO_MTX: std::sync::Mutex<()> = std::sync::Mutex::new(());

#[test]
#[cfg(feature = "nightly")]
#[cfg_attr(miri, ignore)]
fn mocked_c_variadic() {
let _m = FOO_MTX.lock();
let ctx = mock_ffi::foo_context();
ctx.expect().returning(|x, y| x * y);
assert_eq!(6, unsafe{mock_ffi::foo(2, 3, 1, 4, 1)});
}

#[test]
#[cfg(feature = "nightly")]
#[cfg_attr(miri, ignore)]
#[ignore = "https://github.com/rust-lang/rust/issues/126836"]
fn panics() {
let _m = FOO_MTX.lock();
unsafe{ mock_ffi::foo(1,2,3) };
}
23 changes: 22 additions & 1 deletion mockall_derive/src/mock_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,28 @@ impl From<MockableModule> for MockItemModule {

// Set the ABI to match the ForeignMod's ABI
// for proper function linkage with external code.
f.sig.abi = Some(ifm.abi.clone());
//
// BUT, use C-unwind instead of C, so we can panic
// from the mock function (rust-lang/rust #74990)
//
// BUT, don't use C-unwind for variadic functions,
// because it doesn't work yet (rust-lang/rust
// #126836)
let needs_c_unwind = if let Some(n) = &ifm.abi.name
{
n.value() == "C" && f.sig.variadic.is_none()
} else {
false
};
f.sig.abi = Some(if needs_c_unwind {
Abi {
extern_token:ifm.abi.extern_token,
name: Some(LitStr::new("C-unwind",
ifm.abi.name.span()))
}
} else {
ifm.abi.clone()
});

let mf = mock_function::Builder::new(&f.sig, &f.vis)
.attrs(&f.attrs)
Expand Down