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:
@@ -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! {
|
||||||
|
|||||||
@@ -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! {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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! {
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 =====
|
||||||
|
|||||||
Reference in New Issue
Block a user