refactor(ffi): return null ptr instead of aborting in C API (#2478)

Make C API functions that return pointers return null in case of a
panic, instead of aborting.

Add ffi_fn! macro rules that enable default error values to be returned
by writing "?= <value>" after an ffi function's body.
This commit is contained in:
Rasmus Nylander
2021-03-26 19:26:44 +01:00
committed by GitHub
parent 68d4e4a3db
commit 895e4cf3fb
7 changed files with 33 additions and 25 deletions

View File

@@ -34,7 +34,7 @@ ffi_fn! {
/// If not configured, this body acts as an empty payload. /// If not configured, this body acts as an empty payload.
fn hyper_body_new() -> *mut hyper_body { fn hyper_body_new() -> *mut hyper_body {
Box::into_raw(Box::new(hyper_body(Body::empty()))) Box::into_raw(Box::new(hyper_body(Body::empty())))
} } ?= ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -66,7 +66,7 @@ ffi_fn! {
Box::into_raw(hyper_task::boxed(async move { Box::into_raw(hyper_task::boxed(async move {
body.0.data().await.map(|res| res.map(hyper_buf)) body.0.data().await.map(|res| res.map(hyper_buf))
})) }))
} } ?= ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -97,7 +97,7 @@ ffi_fn! {
} }
Ok(()) Ok(())
})) }))
} } ?= ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -198,7 +198,7 @@ ffi_fn! {
std::slice::from_raw_parts(buf, len) std::slice::from_raw_parts(buf, len)
}; };
Box::into_raw(Box::new(hyper_buf(Bytes::copy_from_slice(slice)))) Box::into_raw(Box::new(hyper_buf(Bytes::copy_from_slice(slice))))
} } ?= ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -211,7 +211,7 @@ ffi_fn! {
/// consumed/freed. /// consumed/freed.
fn hyper_buf_bytes(buf: *const hyper_buf) -> *const u8 { fn hyper_buf_bytes(buf: *const hyper_buf) -> *const u8 {
unsafe { (*buf).0.as_ptr() } unsafe { (*buf).0.as_ptr() }
} } ?= ptr::null()
} }
ffi_fn! { ffi_fn! {

View File

@@ -57,7 +57,7 @@ ffi_fn! {
hyper_clientconn { tx } hyper_clientconn { tx }
}) })
})) }))
} } ?= std::ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -85,7 +85,7 @@ ffi_fn! {
}; };
Box::into_raw(hyper_task::boxed(fut)) Box::into_raw(hyper_task::boxed(fut))
} } ?= std::ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -110,7 +110,7 @@ ffi_fn! {
builder: conn::Builder::new(), builder: conn::Builder::new(),
exec: WeakExec::new(), exec: WeakExec::new(),
})) }))
} } ?= std::ptr::null_mut()
} }
ffi_fn! { ffi_fn! {

View File

@@ -37,7 +37,7 @@ ffi_fn! {
/// Construct a new HTTP request. /// Construct a new HTTP request.
fn hyper_request_new() -> *mut hyper_request { fn hyper_request_new() -> *mut hyper_request {
Box::into_raw(Box::new(hyper_request(Request::new(Body::empty())))) Box::into_raw(Box::new(hyper_request(Request::new(Body::empty()))))
} } ?= std::ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -114,7 +114,7 @@ ffi_fn! {
/// `hyper_request` has been consumed. /// `hyper_request` has been consumed.
fn hyper_request_headers(req: *mut hyper_request) -> *mut hyper_headers { fn hyper_request_headers(req: *mut hyper_request) -> *mut hyper_headers {
hyper_headers::get_or_default(unsafe { &mut *req }.0.extensions_mut()) hyper_headers::get_or_default(unsafe { &mut *req }.0.extensions_mut())
} } ?= std::ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -170,7 +170,7 @@ ffi_fn! {
/// buffer. /// buffer.
fn hyper_response_reason_phrase(resp: *const hyper_response) -> *const u8 { fn hyper_response_reason_phrase(resp: *const hyper_response) -> *const u8 {
unsafe { &*resp }.reason_phrase().as_ptr() unsafe { &*resp }.reason_phrase().as_ptr()
} } ?= std::ptr::null()
} }
ffi_fn! { ffi_fn! {
@@ -210,7 +210,7 @@ ffi_fn! {
/// `hyper_response` has been freed. /// `hyper_response` has been freed.
fn hyper_response_headers(resp: *mut hyper_response) -> *mut hyper_headers { fn hyper_response_headers(resp: *mut hyper_response) -> *mut hyper_headers {
hyper_headers::get_or_default(unsafe { &mut *resp }.0.extensions_mut()) hyper_headers::get_or_default(unsafe { &mut *resp }.0.extensions_mut())
} } ?= std::ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -220,7 +220,7 @@ ffi_fn! {
fn hyper_response_body(resp: *mut hyper_response) -> *mut hyper_body { fn hyper_response_body(resp: *mut hyper_response) -> *mut hyper_body {
let body = std::mem::take(unsafe { &mut *resp }.0.body_mut()); let body = std::mem::take(unsafe { &mut *resp }.0.body_mut());
Box::into_raw(Box::new(hyper_body(body))) Box::into_raw(Box::new(hyper_body(body)))
} } ?= std::ptr::null_mut()
} }
impl hyper_response { impl hyper_response {

View File

@@ -37,7 +37,7 @@ ffi_fn! {
write: write_noop, write: write_noop,
userdata: std::ptr::null_mut(), userdata: std::ptr::null_mut(),
})) }))
} } ?= std::ptr::null_mut()
} }
ffi_fn! { ffi_fn! {

View File

@@ -1,5 +1,5 @@
macro_rules! ffi_fn { macro_rules! ffi_fn {
($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) -> $ret:ty $body:block) => { ($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) -> $ret:ty $body:block ?= $default:expr) => {
$(#[$doc])* $(#[$doc])*
#[no_mangle] #[no_mangle]
pub extern fn $name($($arg: $arg_ty),*) -> $ret { pub extern fn $name($($arg: $arg_ty),*) -> $ret {
@@ -8,13 +8,21 @@ macro_rules! ffi_fn {
match panic::catch_unwind(AssertUnwindSafe(move || $body)) { match panic::catch_unwind(AssertUnwindSafe(move || $body)) {
Ok(v) => v, Ok(v) => v,
Err(_) => { Err(_) => {
// TODO: We shouldn't abort, but rather figure out how to $default
// convert into the return type that the function errored. }
}
}
};
($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) -> $ret:ty $body:block) => {
ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> $ret $body ?= {
eprintln!("panic unwind caught, aborting"); eprintln!("panic unwind caught, aborting");
std::process::abort(); std::process::abort()
} });
} };
}
($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) $body:block ?= $default:expr) => {
ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> () $body ?= $default);
}; };
($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) $body:block) => { ($(#[$doc:meta])* fn $name:ident($($arg:ident: $arg_ty:ty),*) $body:block) => {

View File

@@ -92,5 +92,5 @@ ffi_fn! {
/// Returns a static ASCII (null terminated) string of the hyper version. /// Returns a static ASCII (null terminated) string of the hyper version.
fn hyper_version() -> *const libc::c_char { fn hyper_version() -> *const libc::c_char {
VERSION_CSTR.as_ptr() as _ VERSION_CSTR.as_ptr() as _
} } ?= std::ptr::null()
} }

View File

@@ -189,7 +189,7 @@ ffi_fn! {
/// Creates a new task executor. /// Creates a new task executor.
fn hyper_executor_new() -> *const hyper_executor { fn hyper_executor_new() -> *const hyper_executor {
Arc::into_raw(hyper_executor::new()) Arc::into_raw(hyper_executor::new())
} } ?= ptr::null()
} }
ffi_fn! { ffi_fn! {
@@ -230,7 +230,7 @@ ffi_fn! {
Some(task) => Box::into_raw(task), Some(task) => Box::into_raw(task),
None => ptr::null_mut(), None => ptr::null_mut(),
} }
} } ?= ptr::null_mut()
} }
// ===== impl hyper_task ===== // ===== impl hyper_task =====
@@ -303,7 +303,7 @@ ffi_fn! {
} else { } else {
ptr::null_mut() ptr::null_mut()
} }
} } ?= ptr::null_mut()
} }
ffi_fn! { ffi_fn! {
@@ -341,7 +341,7 @@ ffi_fn! {
} }
unsafe { &*task }.userdata.0 unsafe { &*task }.userdata.0
} } ?= ptr::null_mut()
} }
// ===== impl AsTaskType ===== // ===== impl AsTaskType =====
@@ -405,7 +405,7 @@ ffi_fn! {
fn hyper_context_waker(cx: *mut hyper_context<'_>) -> *mut hyper_waker { fn hyper_context_waker(cx: *mut hyper_context<'_>) -> *mut hyper_waker {
let waker = unsafe { &mut *cx }.0.waker().clone(); let waker = unsafe { &mut *cx }.0.waker().clone();
Box::into_raw(Box::new(hyper_waker { waker })) Box::into_raw(Box::new(hyper_waker { waker }))
} } ?= ptr::null_mut()
} }
// ===== impl hyper_waker ===== // ===== impl hyper_waker =====