From 362525fd0001a9ecf4a41bf647225a40016542e8 Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Thu, 5 Jun 2025 03:30:20 -0400 Subject: [PATCH] Add experimental "no-panic" feature. When enabled, any "this should never happen" errors in dispatcher and/or hostcalls will be logged, but the processing will continue as if nothing happened, instead of panicking and trapping WasmVM. Note that any execution past the "should have panicked" point is undefined, since the state of contexts can get out-of-sync with the host when errors and/or events are being ignored. Signed-off-by: Piotr Sikora --- BUILD | 14 + Cargo.toml | 4 + examples/http_auth_random/Cargo.toml | 2 +- src/dispatcher.rs | 224 ++++++++------- src/hostcalls.rs | 391 +++++++++++++++++++++++---- src/logger.rs | 17 ++ 6 files changed, 505 insertions(+), 147 deletions(-) diff --git a/BUILD b/BUILD index 7f611e4f..483e5ad4 100644 --- a/BUILD +++ b/BUILD @@ -39,6 +39,20 @@ rust_library( ], ) +rust_library( + name = "proxy_wasm_no_panic", + srcs = glob(["src/*.rs"]), + crate_features = ["no-panic"], + crate_name = "proxy_wasm", + edition = "2018", + visibility = ["//visibility:public"], + deps = [ + ":proxy_wasm_build_script", + "//bazel/cargo/remote:hashbrown", + "//bazel/cargo/remote:log", + ], +) + rust_binary( name = "http_auth_random", srcs = ["examples/http_auth_random/src/lib.rs"], diff --git a/Cargo.toml b/Cargo.toml index d51e2d86..8b1eb0ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,10 @@ build = "build.rs" hashbrown = "0.15" log = "0.4" +[features] +default = [] +no-panic = [] + [profile.release] lto = true opt-level = 3 diff --git a/examples/http_auth_random/Cargo.toml b/examples/http_auth_random/Cargo.toml index 69be9845..0bd54abe 100644 --- a/examples/http_auth_random/Cargo.toml +++ b/examples/http_auth_random/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib"] [dependencies] log = "0.4" -proxy-wasm = { path = "../../" } +proxy-wasm = { path = "../../", features = ["no-panic"] } [profile.release] lto = true diff --git a/src/dispatcher.rs b/src/dispatcher.rs index 19742565..5023f4cc 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -15,8 +15,8 @@ use crate::hostcalls; use crate::traits::*; use crate::types::*; +use crate::{dont_panic, maybe_panic}; use hashbrown::HashMap; -use log::trace; use std::cell::{Cell, RefCell}; thread_local! { @@ -100,7 +100,7 @@ impl Dispatcher { .insert(token_id, self.active_id.get()) .is_some() { - panic!("duplicate token_id") + maybe_panic!("register_callout: duplicate token_id") } } @@ -111,7 +111,7 @@ impl Dispatcher { .insert(token_id, self.active_id.get()) .is_some() { - panic!("duplicate token_id") + maybe_panic!("register_grpc_stream: duplicate token_id") } } @@ -122,7 +122,7 @@ impl Dispatcher { .insert(token_id, self.active_id.get()) .is_some() { - panic!("duplicate token_id") + maybe_panic!("register_grpc_callout: duplicate token_id") } } @@ -137,49 +137,62 @@ impl Dispatcher { .insert(context_id, new_context) .is_some() { - panic!("duplicate context_id") + maybe_panic!("create_root_context: duplicate context_id") } } fn create_stream_context(&self, context_id: u32, root_context_id: u32) { let new_context = match self.roots.borrow().get(&root_context_id) { Some(root_context) => match self.new_stream.get() { - Some(f) => f(context_id, root_context_id), - None => match root_context.create_stream_context(context_id) { - Some(stream_context) => stream_context, - None => panic!("create_stream_context returned None"), - }, + Some(f) => Some(f(context_id, root_context_id)), + None => root_context.create_stream_context(context_id), }, - None => panic!("invalid root_context_id"), + None => { + maybe_panic!("create_stream_context: invalid root_context_id"); + #[allow(unreachable_code)] + None + } }; - if self - .streams - .borrow_mut() - .insert(context_id, new_context) - .is_some() - { - panic!("duplicate context_id") + match new_context { + Some(new_context) => { + if self + .streams + .borrow_mut() + .insert(context_id, new_context) + .is_some() + { + maybe_panic!("create_stream_context: duplicate context_id") + } + } + None => maybe_panic!("create_stream_context: no context created"), } } fn create_http_context(&self, context_id: u32, root_context_id: u32) { let new_context = match self.roots.borrow().get(&root_context_id) { Some(root_context) => match self.new_http_stream.get() { - Some(f) => f(context_id, root_context_id), - None => match root_context.create_http_context(context_id) { - Some(stream_context) => stream_context, - None => panic!("create_http_context returned None"), - }, + Some(f) => Some(f(context_id, root_context_id)), + None => root_context.create_http_context(context_id), }, - None => panic!("invalid root_context_id"), + None => { + maybe_panic!("create_http_context:invalid root_context_id"); + #[allow(unreachable_code)] + None + } }; - if self - .http_streams - .borrow_mut() - .insert(context_id, new_context) - .is_some() - { - panic!("duplicate context_id") + + match new_context { + Some(new_context) => { + if self + .http_streams + .borrow_mut() + .insert(context_id, new_context) + .is_some() + { + maybe_panic!("create_http_context: duplicate context_id") + } + } + None => maybe_panic!("create_http_context: no context created"), } } @@ -198,10 +211,10 @@ impl Dispatcher { Some(ContextType::StreamContext) => { self.create_stream_context(context_id, root_context_id) } - None => panic!("missing ContextType on root_context"), + None => maybe_panic!("on_create_context: missing ContextType on root_context"), } } else { - panic!("invalid root_context_id and missing constructors"); + maybe_panic!("on_create_context: invalid root_context_id and missing constructors") } } @@ -216,7 +229,9 @@ impl Dispatcher { self.active_id.set(context_id); root.on_done() } else { - panic!("invalid context_id") + maybe_panic!("on_done: invalid context_id"); + #[allow(unreachable_code)] + true } } @@ -231,7 +246,7 @@ impl Dispatcher { self.active_id.set(context_id); root.on_log() } else { - panic!("invalid context_id") + maybe_panic!("on_log: invalid context_id") } } @@ -240,7 +255,7 @@ impl Dispatcher { || self.streams.borrow_mut().remove(&context_id).is_some() || self.roots.borrow_mut().remove(&context_id).is_some()) { - panic!("invalid context_id") + maybe_panic!("on_delete: invalid context_id") } } @@ -249,7 +264,9 @@ impl Dispatcher { self.active_id.set(context_id); root.on_vm_start(vm_configuration_size) } else { - panic!("invalid context_id") + maybe_panic!("on_vm_start: invalid context_id"); + #[allow(unreachable_code)] + true } } @@ -258,7 +275,9 @@ impl Dispatcher { self.active_id.set(context_id); root.on_configure(plugin_configuration_size) } else { - panic!("invalid context_id") + maybe_panic!("on_configure: invalid context_id"); + #[allow(unreachable_code)] + true } } @@ -267,7 +286,7 @@ impl Dispatcher { self.active_id.set(context_id); root.on_tick() } else { - panic!("invalid context_id") + maybe_panic!("on_tick: invalid context_id") } } @@ -276,7 +295,7 @@ impl Dispatcher { self.active_id.set(context_id); root.on_queue_ready(queue_id) } else { - panic!("invalid context_id") + maybe_panic!("on_queue_ready: invalid context_id") } } @@ -285,7 +304,9 @@ impl Dispatcher { self.active_id.set(context_id); stream.on_new_connection() } else { - panic!("invalid context_id") + maybe_panic!("on_new_connection: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -294,7 +315,9 @@ impl Dispatcher { self.active_id.set(context_id); stream.on_downstream_data(data_size, end_of_stream) } else { - panic!("invalid context_id") + maybe_panic!("on_downstream_data: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -303,7 +326,7 @@ impl Dispatcher { self.active_id.set(context_id); stream.on_downstream_close(peer_type) } else { - panic!("invalid context_id") + maybe_panic!("on_downstream_close: invalid context_id") } } @@ -312,7 +335,9 @@ impl Dispatcher { self.active_id.set(context_id); stream.on_upstream_data(data_size, end_of_stream) } else { - panic!("invalid context_id") + maybe_panic!("on_upstream_data: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -321,7 +346,7 @@ impl Dispatcher { self.active_id.set(context_id); stream.on_upstream_close(peer_type) } else { - panic!("invalid context_id") + maybe_panic!("on_upstream_close: invalid context_id") } } @@ -335,7 +360,9 @@ impl Dispatcher { self.active_id.set(context_id); http_stream.on_http_request_headers(num_headers, end_of_stream) } else { - panic!("invalid context_id") + maybe_panic!("on_http_request_headers: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -349,7 +376,9 @@ impl Dispatcher { self.active_id.set(context_id); http_stream.on_http_request_body(body_size, end_of_stream) } else { - panic!("invalid context_id") + maybe_panic!("on_http_request_body: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -358,7 +387,9 @@ impl Dispatcher { self.active_id.set(context_id); http_stream.on_http_request_trailers(num_trailers) } else { - panic!("invalid context_id") + maybe_panic!("on_http_request_trailers: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -372,7 +403,9 @@ impl Dispatcher { self.active_id.set(context_id); http_stream.on_http_response_headers(num_headers, end_of_stream) } else { - panic!("invalid context_id") + maybe_panic!("on_http_response_headers: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -386,7 +419,9 @@ impl Dispatcher { self.active_id.set(context_id); http_stream.on_http_response_body(body_size, end_of_stream) } else { - panic!("invalid context_id") + maybe_panic!("on_http_response_body: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -395,7 +430,9 @@ impl Dispatcher { self.active_id.set(context_id); http_stream.on_http_response_trailers(num_trailers) } else { - panic!("invalid context_id") + maybe_panic!("on_http_response_trailers: invalid context_id"); + #[allow(unreachable_code)] + Action::Continue } } @@ -406,24 +443,23 @@ impl Dispatcher { body_size: usize, num_trailers: usize, ) { - let context_id = self - .callouts - .borrow_mut() - .remove(&token_id) - .expect("invalid token_id"); - - if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { - self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); - http_stream.on_http_call_response(token_id, num_headers, body_size, num_trailers) - } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { - self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); - stream.on_http_call_response(token_id, num_headers, body_size, num_trailers) - } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { - self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); - root.on_http_call_response(token_id, num_headers, body_size, num_trailers) + let context_id = self.callouts.borrow_mut().remove(&token_id); + if let Some(context_id) = context_id { + if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { + self.active_id.set(context_id); + hostcalls::set_effective_context(context_id).unwrap_or(()); + http_stream.on_http_call_response(token_id, num_headers, body_size, num_trailers) + } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { + self.active_id.set(context_id); + hostcalls::set_effective_context(context_id).unwrap_or(()); + stream.on_http_call_response(token_id, num_headers, body_size, num_trailers) + } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { + self.active_id.set(context_id); + hostcalls::set_effective_context(context_id).unwrap_or(()); + root.on_http_call_response(token_id, num_headers, body_size, num_trailers) + } + } else { + maybe_panic!("on_http_call_response: invalid token_id") } } @@ -432,22 +468,22 @@ impl Dispatcher { Some(id) => *id, None => { // TODO: change back to a panic once underlying issue is fixed. - trace!("on_grpc_receive_initial_metadata: invalid token_id"); + dont_panic!("on_grpc_receive_initial_metadata: invalid token_id"); return; } }; if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); http_stream.on_grpc_stream_initial_metadata(token_id, headers); } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); stream.on_grpc_stream_initial_metadata(token_id, headers); } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); root.on_grpc_stream_initial_metadata(token_id, headers); } } @@ -457,15 +493,15 @@ impl Dispatcher { if let Some(context_id) = context_id { if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); http_stream.on_grpc_call_response(token_id, 0, response_size); } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); stream.on_grpc_call_response(token_id, 0, response_size); } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); root.on_grpc_call_response(token_id, 0, response_size); } } else { @@ -473,20 +509,20 @@ impl Dispatcher { if let Some(context_id) = context_id { if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); http_stream.on_grpc_stream_message(token_id, response_size); } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); stream.on_grpc_stream_message(token_id, response_size); } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); root.on_grpc_stream_message(token_id, response_size); } } else { // TODO: change back to a panic once underlying issue is fixed. - trace!("on_grpc_receive_initial_metadata: invalid token_id"); + dont_panic!("on_grpc_receive_initial_metadata: invalid token_id") } } } @@ -496,22 +532,22 @@ impl Dispatcher { Some(id) => *id, None => { // TODO: change back to a panic once underlying issue is fixed. - trace!("on_grpc_receive_trailing_metadata: invalid token_id"); + dont_panic!("on_grpc_receive_trailing_metadata: invalid token_id"); return; } }; if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); http_stream.on_grpc_stream_trailing_metadata(token_id, trailers); } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); stream.on_grpc_stream_trailing_metadata(token_id, trailers); } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); root.on_grpc_stream_trailing_metadata(token_id, trailers); } } @@ -521,15 +557,15 @@ impl Dispatcher { if let Some(context_id) = context_id { if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); http_stream.on_grpc_call_response(token_id, status_code, 0); } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); stream.on_grpc_call_response(token_id, status_code, 0); } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); root.on_grpc_call_response(token_id, status_code, 0); } } else { @@ -537,20 +573,20 @@ impl Dispatcher { if let Some(context_id) = context_id { if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); http_stream.on_grpc_stream_close(token_id, status_code) } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); stream.on_grpc_stream_close(token_id, status_code) } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); root.on_grpc_stream_close(token_id, status_code) } } else { // TODO: change back to a panic once underlying issue is fixed. - trace!("on_grpc_close: invalid token_id, a non-connected stream has closed"); + dont_panic!("on_grpc_close: invalid token_id, a non-connected stream has closed") } } } @@ -558,15 +594,15 @@ impl Dispatcher { fn on_foreign_function(&self, context_id: u32, function_id: u32, arugments_size: usize) { if let Some(http_stream) = self.http_streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); http_stream.on_foreign_function(function_id, arugments_size) } else if let Some(stream) = self.streams.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); stream.on_foreign_function(function_id, arugments_size) } else if let Some(root) = self.roots.borrow_mut().get_mut(&context_id) { self.active_id.set(context_id); - hostcalls::set_effective_context(context_id).unwrap(); + hostcalls::set_effective_context(context_id).unwrap_or(()); root.on_foreign_function(function_id, arugments_size) } } diff --git a/src/hostcalls.rs b/src/hostcalls.rs index 76c3513d..d2b10488 100644 --- a/src/hostcalls.rs +++ b/src/hostcalls.rs @@ -13,6 +13,7 @@ // limitations under the License. use crate::dispatcher; +use crate::maybe_panic; use crate::types::*; use std::ptr::{null, null_mut}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -25,7 +26,11 @@ pub fn log(level: LogLevel, message: &str) -> Result<(), Status> { unsafe { match proxy_log(level, message.as_ptr(), message.len()) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_log unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -39,7 +44,11 @@ pub fn get_log_level() -> Result { unsafe { match proxy_get_log_level(&mut return_level) { Status::Ok => Ok(return_level), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_get_log_level unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -53,7 +62,14 @@ pub fn get_current_time() -> Result { unsafe { match proxy_get_current_time_nanoseconds(&mut return_time) { Status::Ok => Ok(UNIX_EPOCH + Duration::from_nanos(return_time)), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_get_current_time_nanoseconds unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -66,7 +82,14 @@ pub fn set_tick_period(period: Duration) -> Result<(), Status> { unsafe { match proxy_set_tick_period_milliseconds(period.as_millis() as u32) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_set_tick_period_milliseconds unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -108,7 +131,14 @@ pub fn get_buffer( } } Status::NotFound => Ok(None), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_get_buffer_bytes unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -132,7 +162,14 @@ pub fn set_buffer( unsafe { match proxy_set_buffer_bytes(buffer_type, start, size, value.as_ptr(), value.len()) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_set_buffer_bytes unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -158,7 +195,14 @@ pub fn get_map(map_type: MapType) -> Result, Status> { Ok(Vec::new()) } } - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_get_header_map_pairs unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -176,7 +220,14 @@ pub fn get_map_bytes(map_type: MapType) -> Result, Status> Ok(Vec::new()) } } - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_get_header_map_pairs unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -194,7 +245,14 @@ pub fn set_map(map_type: MapType, map: Vec<(&str, &str)>) -> Result<(), Status> unsafe { match proxy_set_header_map_pairs(map_type, serialized_map.as_ptr(), serialized_map.len()) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_set_header_map_pairs unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -204,7 +262,14 @@ pub fn set_map_bytes(map_type: MapType, map: Vec<(&str, &[u8])>) -> Result<(), S unsafe { match proxy_set_header_map_pairs(map_type, serialized_map.as_ptr(), serialized_map.len()) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_set_header_map_pairs unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -245,7 +310,14 @@ pub fn get_map_value(map_type: MapType, key: &str) -> Result, Sta } } Status::NotFound => Ok(None), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_get_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -273,7 +345,14 @@ pub fn get_map_value_bytes(map_type: MapType, key: &str) -> Result } } Status::NotFound => Ok(None), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_get_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -290,7 +369,14 @@ pub fn remove_map_value(map_type: MapType, key: &str) -> Result<(), Status> { unsafe { match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_remove_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -316,12 +402,26 @@ pub fn set_map_value(map_type: MapType, key: &str, value: Option<&str>) -> Resul value.len(), ) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_replace_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } else { match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_remove_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -342,12 +442,26 @@ pub fn set_map_value_bytes( value.len(), ) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_replace_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } else { match proxy_remove_header_map_value(map_type, key.as_ptr(), key.len()) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_remove_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -373,7 +487,14 @@ pub fn add_map_value(map_type: MapType, key: &str, value: &str) -> Result<(), St value.len(), ) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_add_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -388,7 +509,14 @@ pub fn add_map_value_bytes(map_type: MapType, key: &str, value: &[u8]) -> Result value.len(), ) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_add_header_map_value unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -427,7 +555,11 @@ pub fn get_property(path: Vec<&str>) -> Result, Status> { Status::NotFound => Ok(None), Status::SerializationFailure => Err(Status::SerializationFailure), Status::InternalFailure => Err(Status::InternalFailure), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_get_property unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -451,7 +583,11 @@ pub fn set_property(path: Vec<&str>, value: Option<&[u8]>) -> Result<(), Status> value.map_or(0, |value| value.len()), ) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_set_property unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -493,7 +629,11 @@ pub fn get_shared_data(key: &str) -> Result<(Option, Option), Status } } Status::NotFound => Ok((None, None)), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_get_shared_data unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -519,7 +659,11 @@ pub fn set_shared_data(key: &str, value: Option<&[u8]>, cas: Option) -> Res ) { Status::Ok => Ok(()), Status::CasMismatch => Err(Status::CasMismatch), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_set_shared_data unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -537,7 +681,14 @@ pub fn register_shared_queue(name: &str) -> Result { let mut return_id: u32 = 0; match proxy_register_shared_queue(name.as_ptr(), name.len(), &mut return_id) { Status::Ok => Ok(return_id), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_register_shared_queue unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -564,7 +715,14 @@ pub fn resolve_shared_queue(vm_id: &str, name: &str) -> Result, Stat ) { Status::Ok => Ok(Some(return_id)), Status::NotFound => Ok(None), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_resolve_shared_queue unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -595,7 +753,14 @@ pub fn dequeue_shared_queue(queue_id: u32) -> Result, Status> { } Status::Empty => Ok(None), Status::NotFound => Err(Status::NotFound), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_dequeue_shared_queue unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -617,7 +782,14 @@ pub fn enqueue_shared_queue(queue_id: u32, value: Option<&[u8]>) -> Result<(), S ) { Status::Ok => Ok(()), Status::NotFound => Err(Status::NotFound), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_enqueue_shared_queue unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -630,7 +802,11 @@ pub fn resume_downstream() -> Result<(), Status> { unsafe { match proxy_continue_stream(StreamType::Downstream) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_continue_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -639,7 +815,11 @@ pub fn resume_upstream() -> Result<(), Status> { unsafe { match proxy_continue_stream(StreamType::Upstream) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_continue_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -648,7 +828,11 @@ pub fn resume_http_request() -> Result<(), Status> { unsafe { match proxy_continue_stream(StreamType::HttpRequest) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_continue_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -657,7 +841,11 @@ pub fn resume_http_response() -> Result<(), Status> { unsafe { match proxy_continue_stream(StreamType::HttpResponse) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_continue_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -670,7 +858,11 @@ pub fn close_downstream() -> Result<(), Status> { unsafe { match proxy_close_stream(StreamType::Downstream) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_close_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -678,7 +870,11 @@ pub fn close_upstream() -> Result<(), Status> { unsafe { match proxy_close_stream(StreamType::Upstream) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_close_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -687,7 +883,11 @@ pub fn reset_http_request() -> Result<(), Status> { unsafe { match proxy_close_stream(StreamType::HttpRequest) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_close_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -696,7 +896,11 @@ pub fn reset_http_response() -> Result<(), Status> { unsafe { match proxy_close_stream(StreamType::HttpResponse) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_close_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -732,7 +936,14 @@ pub fn send_http_response( -1, ) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_send_local_response unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -755,7 +966,14 @@ pub fn send_grpc_response( grpc_status as i32, ) { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_send_local_response unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -804,7 +1022,11 @@ pub fn dispatch_http_call( } Status::BadArgument => Err(Status::BadArgument), Status::InternalFailure => Err(Status::InternalFailure), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_http_call unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -857,7 +1079,11 @@ pub fn dispatch_grpc_call( } Status::ParseFailure => Err(Status::ParseFailure), Status::InternalFailure => Err(Status::InternalFailure), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_grpc_call unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -902,7 +1128,11 @@ pub fn open_grpc_stream( } Status::ParseFailure => Err(Status::ParseFailure), Status::InternalFailure => Err(Status::InternalFailure), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_grpc_stream unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -931,7 +1161,11 @@ pub fn send_grpc_stream_message( Status::Ok => Ok(()), Status::BadArgument => Err(Status::BadArgument), Status::NotFound => Err(Status::NotFound), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_grpc_send unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -945,7 +1179,11 @@ pub fn cancel_grpc_call(token_id: u32) -> Result<(), Status> { match proxy_grpc_cancel(token_id) { Status::Ok => Ok(()), Status::NotFound => Err(Status::NotFound), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_grpc_cancel unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -955,7 +1193,11 @@ pub fn cancel_grpc_stream(token_id: u32) -> Result<(), Status> { match proxy_grpc_cancel(token_id) { Status::Ok => Ok(()), Status::NotFound => Err(Status::NotFound), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_grpc_cancel unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -969,7 +1211,11 @@ pub fn close_grpc_stream(token_id: u32) -> Result<(), Status> { match proxy_grpc_close(token_id) { Status::Ok => Ok(()), Status::NotFound => Err(Status::NotFound), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_grpc_close unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1005,7 +1251,11 @@ pub fn get_grpc_status() -> Result<(u32, Option), Status> { Ok((return_code, None)) } } - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_get_status unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1019,7 +1269,14 @@ pub fn set_effective_context(context_id: u32) -> Result<(), Status> { match proxy_set_effective_context(context_id) { Status::Ok => Ok(()), Status::BadArgument => Err(Status::BadArgument), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_set_effective_context unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1065,7 +1322,14 @@ pub fn call_foreign_function( Status::BadArgument => Err(Status::BadArgument), Status::SerializationFailure => Err(Status::SerializationFailure), Status::InternalFailure => Err(Status::InternalFailure), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_call_foreign_function unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1078,7 +1342,11 @@ pub fn done() -> Result<(), Status> { unsafe { match proxy_done() { Status::Ok => Ok(()), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_done unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1097,7 +1365,11 @@ pub fn define_metric(metric_type: MetricType, name: &str) -> Result unsafe { match proxy_define_metric(metric_type, name.as_ptr(), name.len(), &mut return_id) { Status::Ok => Ok(return_id), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_define_metric unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1113,7 +1385,11 @@ pub fn get_metric(metric_id: u32) -> Result { Status::Ok => Ok(return_value), Status::NotFound => Err(Status::NotFound), Status::BadArgument => Err(Status::BadArgument), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_get_metric unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1127,7 +1403,11 @@ pub fn record_metric(metric_id: u32, value: u64) -> Result<(), Status> { match proxy_record_metric(metric_id, value) { Status::Ok => Ok(()), Status::NotFound => Err(Status::NotFound), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!("proxy_record_metric unexpected status: {}", status as u32); + #[allow(unreachable_code)] + Err(status) + } } } } @@ -1142,7 +1422,14 @@ pub fn increment_metric(metric_id: u32, offset: i64) -> Result<(), Status> { Status::Ok => Ok(()), Status::NotFound => Err(Status::NotFound), Status::BadArgument => Err(Status::BadArgument), - status => panic!("unexpected status: {}", status as u32), + status => { + maybe_panic!( + "proxy_increment_metric unexpected status: {}", + status as u32 + ); + #[allow(unreachable_code)] + Err(status) + } } } } diff --git a/src/logger.rs b/src/logger.rs index 050a356d..97a3b765 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -17,6 +17,23 @@ use crate::types::LogLevel; use std::panic; use std::sync::atomic::{AtomicBool, Ordering}; +#[cfg(not(feature = "no-panic"))] +#[macro_export] +macro_rules! maybe_panic { + ($($arg:tt)*) => { panic!($($arg)*) }; +} + +#[cfg(feature = "no-panic")] +#[macro_export] +macro_rules! maybe_panic { + ($($arg:tt)*) => { $crate::hostcalls::log(LogLevel::Critical, format!($($arg)*).as_str()).unwrap_or(()) }; +} + +#[macro_export] +macro_rules! dont_panic { + ($($arg:tt)*) => { $crate::hostcalls::log(LogLevel::Critical, format!($($arg)*).as_str()).unwrap_or(()) }; +} + struct Logger; static LOGGER: Logger = Logger;