hmon: rework error handling in FFI#87
Conversation
License Check Results🚀 The license check job ran with the Bazel command: bazel run //:license-checkStatus: Click to expand output |
|
The created documentation from the pull request is available at: docu-html |
There was a problem hiding this comment.
Pull request overview
This PR reworks the Health Monitoring (HMON) Rust↔C++ FFI surface to use a uniform return-code-based error model, updates the C++ wrappers to construct objects via factory methods returning expected, and adds Rust unit tests covering the FFI functions (in support of avoiding panics/terminates across extern "C" boundaries).
Changes:
- Introduce a shared
FFICodeand convert Rust FFI functions to return it (with out-params for handles). - Update C++ wrappers/builders to use
::create()factory methods andexpected<..., Error>for fallible construction/build. - Add/expand Rust unit tests for FFI functions and adjust the C++ tests to the new API.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| src/health_monitoring_lib/rust/lib.rs | Documentation tweak for builder creation/build. |
| src/health_monitoring_lib/rust/ffi.rs | New FFICode/FFIHandle, reworked HM FFI API + extensive Rust tests. |
| src/health_monitoring_lib/rust/deadline/ffi.rs | Reworked deadline FFI API to FFICode + Rust tests. |
| src/health_monitoring_lib/rust/common.rs | Removes old common::ffi module in favor of crate::ffi. |
| src/health_monitoring_lib/cpp/include/score/hm/common.h | Introduces internal FFICode/kSuccess, updates Error codes & drop-fn signature. |
| src/health_monitoring_lib/cpp/include/score/hm/health_monitor.h | Builder now uses create() + expected and build() becomes fallible. |
| src/health_monitoring_lib/cpp/include/score/hm/deadline/deadline_monitor.h | Deadline builder now uses create() + expected. |
| src/health_monitoring_lib/cpp/health_monitor.cpp | Implements new FFI signatures and expected-based factory/build paths. |
| src/health_monitoring_lib/cpp/deadline_monitor.cpp | Implements new FFI signatures and expected-based factory paths. |
| src/health_monitoring_lib/cpp/tests/health_monitor_test.cpp | Updates test to use create().value() and fallible build().value(). |
| src/health_monitoring_lib/BUILD | Removes deleted cpp/ffi_helpers.h from sources. |
| src/health_monitoring_lib/cpp/ffi_helpers.h | Deleted legacy error mapping helper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let mut health_monitor = FFIBorrowed::new(unsafe { Box::from_raw(health_monitor_handle as *mut HealthMonitor) }); | ||
|
|
||
| health_monitor.start(); | ||
|
|
||
| // Safety: We ensure that the pointer is valid. We assume that pointer was created by call to `health_monitor_builder_build` | ||
| // and this must be assured on other side of FFI. | ||
| let mut monitor = FFIBorrowed::new(unsafe { Box::from_raw(handle as *mut HealthMonitor) }); | ||
| monitor.start(); | ||
| FFICode::Success |
There was a problem hiding this comment.
health_monitor_start calls HealthMonitor::start(), which contains multiple assert!/panic! paths (e.g., no monitors, monitors not taken, invalid state). Any of these will abort when invoked through FFI. Pre-check the required invariants in this wrapper (and return FFICode::WrongState/InvalidArgument) or use catch_unwind so FFI callers can observe an error code instead of process termination.
There was a problem hiding this comment.
True. but when i read https://doc.rust-lang.org/std/panic/fn.catch_unwind.html extern "c" shall be ok . we can still catchunwind and abort on cpp side.
f78336e to
507d936
Compare
| assert!(!handle.is_null()); | ||
| assert!(!tag.is_null()); | ||
| assert!(!monitor.is_null()); | ||
| pub extern "C" fn health_monitor_builder_create(health_monitor_builder_handle: *mut FFIHandle) -> FFICode { |
There was a problem hiding this comment.
For consistency and unit testing across ffi modules.
crate::deadline::ffi already had pub functions, and I need access to HMON functions from it to test it - otherwise deadline monitor cannot be obtained.
This shouldn't matter, as all ffi modules are crate-internal. I can replace pub with pub(crate) but this increases visual noise.
| *deadline_handle = core::ptr::null_mut(); | ||
| } | ||
| HM_OK | ||
| e |
src/health_monitoring_lib/cpp/include/score/hm/health_monitor.h
Outdated
Show resolved
Hide resolved
507d936 to
d179c88
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
d179c88 to
4b2a346
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/health_monitoring_lib/cpp/health_monitor.cpp:136
- The destructor calls health_monitor_destroy but ignores the returned FFICode. While ignoring errors in destructors is sometimes acceptable, this inconsistency could mask issues. Consider using abort_on_error for consistency with other parts of the codebase, or explicitly document why errors are ignored in destructors.
HealthMonitor::~HealthMonitor()
{
if (health_monitor_ != nullptr)
{
health_monitor_destroy(health_monitor_);
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| &deadline_monitor_tag as *const IdentTag, | ||
| deadline_monitor_builder_handle, | ||
| ); | ||
| assert!(!deadline_monitor_builder_handle.is_null()); |
There was a problem hiding this comment.
Incorrect assertion: After health_monitor_builder_add_deadline_monitor succeeds, the deadline_monitor_builder_handle has been consumed (the pointer was unboxed and the builder was moved). Asserting that the handle is not null checks a dangling pointer value. This assertion should be removed as it doesn't test anything meaningful and could give false confidence.
| assert!(!deadline_monitor_builder_handle.is_null()); |
4b2a346 to
6f0335a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn health_monitor_builder_add_deadline_monitor_null_hmon_builder() { | ||
| let mut deadline_monitor_builder_handle: FFIHandle = null_mut(); | ||
|
|
||
| let deadline_monitor_tag = IdentTag::new("deadline_monitor"); | ||
| let _ = deadline_monitor_builder_create(&mut deadline_monitor_builder_handle as *mut FFIHandle); | ||
|
|
||
| let health_monitor_builder_add_deadline_monitor_result = health_monitor_builder_add_deadline_monitor( | ||
| null_mut(), | ||
| &deadline_monitor_tag as *const IdentTag, | ||
| deadline_monitor_builder_handle, | ||
| ); | ||
| assert_eq!( | ||
| health_monitor_builder_add_deadline_monitor_result, | ||
| FFICode::NullParameter | ||
| ); | ||
| } |
There was a problem hiding this comment.
The deadline_monitor_builder_handle created at line 371 is never destroyed when the function returns FFICode::NullParameter. This causes a resource leak in the test. Add cleanup by calling deadline_monitor_builder_destroy(deadline_monitor_builder_handle) before the test ends.
6f0335a to
69fcbc8
Compare
- Uniformly return `FFICode` in FFI functions. - Unit tests for FFI functions in Rust. - Rework comments for FFI functions. - Move `crate::common::ffi` to `crate::ffi`.
69fcbc8 to
fcfb27c
Compare
FFICodein FFI functions.crate::common::ffitocrate::ffi.Closes #82