Skip to content

Commit

Permalink
Merge branch 'master' into merge-in-rustler-sys
Browse files Browse the repository at this point in the history
  • Loading branch information
filmor authored Oct 11, 2024
2 parents b1994d4 + 3294997 commit 822be51
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ versions.
now (#638)
- API functions for Windows are correctly assigned now for NIF version 2.15 and
above (#635)
- Panics in encoding the result of NIF function are caught (#656)

### Changed

Expand Down
6 changes: 6 additions & 0 deletions rustler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ serde = { version = "1", optional = true }
[build-dependencies]
regex-lite = "0.1"

[profile.dev]
panic = "unwind"

[profile.release]
panic = "unwind"

[package.metadata.release]

[[package.metadata.release.pre-release-replacements]]
Expand Down
13 changes: 10 additions & 3 deletions rustler/src/codegen_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::ffi::CString;
use std::fmt;

use crate::types::atom;
use crate::{Encoder, Env, OwnedBinary, Term};

// Re-export of inventory
Expand All @@ -26,10 +27,16 @@ pub unsafe trait NifReturnable {

unsafe impl<T> NifReturnable for T
where
T: crate::Encoder,
T: crate::Encoder + std::panic::RefUnwindSafe,
{
unsafe fn into_returned(self, env: Env) -> NifReturned {
NifReturned::Term(self.encode(env).as_c_arg())
if let Ok(res) = std::panic::catch_unwind(|| NifReturned::Term(self.encode(env).as_c_arg()))
{
res
} else {
let term = atom::nif_panicked().as_c_arg();
NifReturned::Raise(term)
}
}
}

Expand Down Expand Up @@ -126,7 +133,7 @@ where
Err(err) => match err.downcast::<NifReturned>() {
Ok(ty) => NifReturned::Term(ty.apply(env)),
Err(_) => {
let term = crate::types::atom::nif_panicked().as_c_arg();
let term = atom::nif_panicked().as_c_arg();
NifReturned::Raise(term)
}
},
Expand Down
7 changes: 0 additions & 7 deletions rustler_mix/lib/rustler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,6 @@ defmodule Rustler do
end

if config.lib do
{otp_app, path} = config.load_from

@external_resource Application.app_dir(
otp_app,
"#{path}.#{Rustler.Compiler.get_lib_suffix()}"
)

@load_from config.load_from
@load_data config.load_data
@load_data_fun config.load_data_fun
Expand Down
2 changes: 0 additions & 2 deletions rustler_mix/lib/rustler/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@ defmodule Rustler.Compiler do
end
end

def get_lib_suffix(), do: get_suffix(nil, :lib)

defp get_suffix(target, :lib) do
case get_target_os_type(target) do
{:win32, _} -> "dll"
Expand Down
4 changes: 4 additions & 0 deletions rustler_tests/lib/rustler_test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ defmodule RustlerTest do

def append_to_path(_path, _to_append), do: err()

def panic_in_nif(), do: err()
def panic_in_encode(), do: err()
def panic_in_decode(_), do: err()

if Helper.has_nif_version("2.16") do
def perform_dyncall(_res, _a, _b, _c), do: err()
end
Expand Down
1 change: 1 addition & 0 deletions rustler_tests/native/rustler_test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod test_list;
mod test_local_pid;
mod test_map;
mod test_nif_attrs;
mod test_panic;
mod test_path;
mod test_primitives;
mod test_range;
Expand Down
30 changes: 30 additions & 0 deletions rustler_tests/native/rustler_test/src/test_panic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use rustler::{Decoder, Encoder, Env, Term};

#[rustler::nif]
pub fn panic_in_nif() -> i32 {
panic!("panic!")
}

struct Panicking;

impl Encoder for Panicking {
fn encode<'a>(&self, _env: Env<'a>) -> Term<'a> {
panic!("panic in encode!")
}
}

impl<'a> Decoder<'a> for Panicking {
fn decode(_term: Term<'a>) -> rustler::NifResult<Self> {
panic!("panic in decode!")
}
}

#[rustler::nif]
pub fn panic_in_encode() -> Panicking {
Panicking
}

#[rustler::nif]
pub fn panic_in_decode(_p: Panicking) -> i32 {
0
}
12 changes: 12 additions & 0 deletions rustler_tests/test/panic_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule PanicTest do
use ExUnit.Case

test "panics in NIFs are caught" do
assert_raise ErlangError, &RustlerTest.panic_in_nif/0
assert_raise ErlangError, &RustlerTest.panic_in_encode/0

assert_raise ErlangError, fn ->
RustlerTest.panic_in_decode(:anything)
end
end
end

0 comments on commit 822be51

Please sign in to comment.