Skip to content

Commit 8443034

Browse files
committed
Update guest-side error handling
- Update guest/host_comm.rs to use new Result-like return values - Update guest_bin/call.rs to properly handle host function errors - Update guest_bin/lib.rs to remove obsolete error handling import and make GUEST_HANDLE public (for use in C-API) - Update guest_capi/error.rs to support new error types Signed-off-by: Ludvig Liljenberg <[email protected]>
1 parent dc6820b commit 8443034

File tree

4 files changed

+66
-44
lines changed

4 files changed

+66
-44
lines changed

src/hyperlight_guest/src/guest_handle/host_comm.rs

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ use core::slice::from_raw_parts;
2222
use flatbuffers::FlatBufferBuilder;
2323
use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType};
2424
use hyperlight_common::flatbuffer_wrappers::function_types::{
25-
ParameterValue, ReturnType, ReturnValue,
25+
FunctionCallResult, ParameterValue, ReturnType, ReturnValue,
2626
};
27-
use hyperlight_common::flatbuffer_wrappers::guest_error::{ErrorCode, GuestError};
27+
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
2828
use hyperlight_common::flatbuffer_wrappers::guest_log_data::GuestLogData;
2929
use hyperlight_common::flatbuffer_wrappers::guest_log_level::LogLevel;
3030
use hyperlight_common::flatbuffer_wrappers::host_function_details::HostFunctionDetails;
@@ -68,18 +68,24 @@ impl GuestHandle {
6868
/// internally to get the return value.
6969
#[hyperlight_guest_tracing::trace_function]
7070
pub fn get_host_return_value<T: TryFrom<ReturnValue>>(&self) -> Result<T> {
71-
let return_value = self
72-
.try_pop_shared_input_data_into::<ReturnValue>()
73-
.expect("Unable to deserialize a return value from host");
74-
T::try_from(return_value).map_err(|_| {
75-
HyperlightGuestError::new(
76-
ErrorCode::GuestError,
77-
format!(
78-
"Host return value was not a {} as expected",
79-
core::any::type_name::<T>()
80-
),
81-
)
82-
})
71+
let inner = self
72+
.try_pop_shared_input_data_into::<FunctionCallResult>()
73+
.expect("Unable to deserialize a return value from host")
74+
.into_inner();
75+
76+
match inner {
77+
Ok(ret) => T::try_from(ret).map_err(|_| {
78+
let expected = core::any::type_name::<T>();
79+
HyperlightGuestError::new(
80+
ErrorCode::UnsupportedParameterType,
81+
format!("Host return value could not be converted to expected {expected}",),
82+
)
83+
}),
84+
Err(e) => Err(HyperlightGuestError {
85+
kind: e.code,
86+
message: e.message,
87+
}),
88+
}
8389
}
8490

8591
/// Call a host function without reading its return value from shared mem.
@@ -148,22 +154,6 @@ impl GuestHandle {
148154
.expect("Failed to convert buffer to HostFunctionDetails")
149155
}
150156

151-
/// Write an error to the shared output data buffer.
152-
#[hyperlight_guest_tracing::trace_function]
153-
pub fn write_error(&self, error_code: ErrorCode, message: Option<&str>) {
154-
let guest_error: GuestError = GuestError::new(
155-
error_code,
156-
message.map_or("".to_string(), |m| m.to_string()),
157-
);
158-
let guest_error_buffer: Vec<u8> = (&guest_error)
159-
.try_into()
160-
.expect("Invalid guest_error_buffer, could not be converted to a Vec<u8>");
161-
162-
if let Err(e) = self.push_shared_output_data(&guest_error_buffer) {
163-
panic!("Unable to push guest error to shared output data: {:#?}", e);
164-
}
165-
}
166-
167157
/// Log a message with the specified log level, source, caller, source file, and line number.
168158
#[hyperlight_guest_tracing::trace_function]
169159
pub fn log_message(

src/hyperlight_guest_bin/src/guest_function/call.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ limitations under the License.
1717
use alloc::format;
1818
use alloc::vec::Vec;
1919

20+
use flatbuffers::FlatBufferBuilder;
2021
use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType};
21-
use hyperlight_common::flatbuffer_wrappers::function_types::ParameterType;
22-
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
22+
use hyperlight_common::flatbuffer_wrappers::function_types::{FunctionCallResult, ParameterType};
23+
use hyperlight_common::flatbuffer_wrappers::guest_error::{ErrorCode, GuestError};
2324
use hyperlight_guest::error::{HyperlightGuestError, Result};
2425
use hyperlight_guest::exit::halt;
2526

@@ -81,10 +82,12 @@ pub(crate) fn call_guest_function(function_call: FunctionCall) -> Result<Vec<u8>
8182

8283
// This function is marked as no_mangle/inline to prevent the compiler from inlining it , if its inlined the epilogue will not be called
8384
// and we will leak memory as the epilogue will not be called as halt() is not going to return.
85+
//
86+
// This function may panic, as we have no other ways of dealing with errors at this level
8487
#[unsafe(no_mangle)]
8588
#[inline(never)]
8689
#[hyperlight_guest_tracing::trace_function]
87-
fn internal_dispatch_function() -> Result<()> {
90+
fn internal_dispatch_function() {
8891
let handle = unsafe { GUEST_HANDLE };
8992

9093
#[cfg(debug_assertions)]
@@ -94,11 +97,24 @@ fn internal_dispatch_function() -> Result<()> {
9497
.try_pop_shared_input_data_into::<FunctionCall>()
9598
.expect("Function call deserialization failed");
9699

97-
let result_vec = call_guest_function(function_call).inspect_err(|e| {
98-
handle.write_error(e.kind, Some(e.message.as_str()));
99-
})?;
100+
let res = call_guest_function(function_call);
100101

101-
handle.push_shared_output_data(&result_vec)
102+
match res {
103+
Ok(bytes) => {
104+
handle
105+
.push_shared_output_data(bytes.as_slice())
106+
.expect("Failed to serialize function call result");
107+
}
108+
Err(err) => {
109+
let guest_error = Err(GuestError::new(err.kind, err.message));
110+
let fcr = FunctionCallResult::new(guest_error);
111+
let mut builder = FlatBufferBuilder::new();
112+
let data = fcr.encode(&mut builder);
113+
handle
114+
.push_shared_output_data(data)
115+
.expect("Failed to serialize function call result");
116+
}
117+
}
102118
}
103119

104120
// This is implemented as a separate function to make sure that epilogue in the internal_dispatch_function is called before the halt()
@@ -117,6 +133,6 @@ pub(crate) extern "C" fn dispatch_function() {
117133
// part of the big identity-mapped region at the base of the
118134
// guest.
119135
crate::paging::flush_tlb();
120-
let _ = internal_dispatch_function();
136+
internal_dispatch_function();
121137
halt();
122138
}

src/hyperlight_guest_bin/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ pub mod exceptions {
4545
pub(super) mod idtr;
4646
mod interrupt_entry;
4747
}
48-
pub mod guest_err;
4948
pub mod guest_function {
5049
pub(super) mod call;
5150
pub mod definition;
@@ -121,7 +120,7 @@ pub(crate) static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::empty();
121120
pub(crate) static HEAP_ALLOCATOR: ProfiledLockedHeap<32> =
122121
ProfiledLockedHeap(LockedHeap::<32>::empty());
123122

124-
pub(crate) static mut GUEST_HANDLE: GuestHandle = GuestHandle::new();
123+
pub static mut GUEST_HANDLE: GuestHandle = GuestHandle::new();
125124
pub(crate) static mut REGISTERED_GUEST_FUNCTIONS: GuestFunctionRegister =
126125
GuestFunctionRegister::new();
127126

src/hyperlight_guest_capi/src/error.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,32 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
use core::ffi::c_char;
17+
use core::ffi::{CStr, c_char};
1818

19-
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
20-
use hyperlight_guest_bin::guest_err::setError;
19+
use flatbuffers::FlatBufferBuilder;
20+
use hyperlight_common::flatbuffer_wrappers::function_types::FunctionCallResult;
21+
use hyperlight_common::flatbuffer_wrappers::guest_error::{ErrorCode, GuestError};
22+
use hyperlight_guest_bin::GUEST_HANDLE;
23+
24+
use crate::alloc::borrow::ToOwned;
2125

2226
#[unsafe(no_mangle)]
2327
pub extern "C" fn hl_set_error(err: ErrorCode, message: *const c_char) {
28+
let cstr = unsafe { CStr::from_ptr(message) };
29+
let guest_error = Err(GuestError::new(
30+
err.into(),
31+
cstr.to_str()
32+
.expect("Failed to convert CStr to &str")
33+
.to_owned(),
34+
));
35+
let fcr = FunctionCallResult::new(guest_error);
36+
let mut builder = FlatBufferBuilder::new();
37+
let data = fcr.encode(&mut builder);
2438
unsafe {
25-
setError(err.into(), message);
39+
#[allow(static_mut_refs)] // we are single threaded
40+
GUEST_HANDLE
41+
.push_shared_output_data(data)
42+
.expect("Failed to set error")
2643
}
2744
}
2845

0 commit comments

Comments
 (0)