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,15 +8,23 @@ 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. |  | ||||||
|                     eprintln!("panic unwind caught, aborting"); |  | ||||||
|                     std::process::abort(); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     ($(#[$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"); | ||||||
|  |             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) => { | ||||||
|         ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> () $body); |         ffi_fn!($(#[$doc])* fn $name($($arg: $arg_ty),*) -> () $body); | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -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