-
Notifications
You must be signed in to change notification settings - Fork 117
fix(wasm): unify error handling for mm2_main #2389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
57844da
6dd335e
64aa899
c26088d
a5c9751
bd480a4
80b9198
af0e328
590e861
f61bac7
299592b
77d26f4
f078571
29c8206
80cfea7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ use enum_primitive_derive::Primitive; | |
| use gstuff::any_to_str; | ||
| use libc::c_char; | ||
| use mm2_core::mm_ctx::MmArc; | ||
| use mm2_main::LpMainParams; | ||
| use num_traits::FromPrimitive; | ||
| use serde_json::{self as json}; | ||
| use std::ffi::{CStr, CString}; | ||
|
|
@@ -15,15 +16,6 @@ use std::sync::atomic::{AtomicBool, Ordering}; | |
| use std::thread; | ||
| use std::time::Duration; | ||
|
|
||
| #[derive(Debug, PartialEq, Primitive)] | ||
| enum MainErr { | ||
| Ok = 0, | ||
| AlreadyRuns = 1, | ||
| ConfIsNull = 2, | ||
| ConfNotUtf8 = 3, | ||
| CantThread = 5, | ||
| } | ||
|
|
||
| /// Starts the MM2 in a detached singleton thread. | ||
| #[no_mangle] | ||
| #[allow(clippy::missing_safety_doc)] | ||
|
|
@@ -48,40 +40,75 @@ pub unsafe extern "C" fn mm2_main(conf: *const c_char, log_cb: extern "C" fn(lin | |
| }}; | ||
| } | ||
|
|
||
| if LP_MAIN_RUNNING.load(Ordering::Relaxed) { | ||
| eret!(MainErr::AlreadyRuns) | ||
| } | ||
| CTX.store(0, Ordering::Relaxed); // Remove the old context ID during restarts. | ||
|
|
||
| if conf.is_null() { | ||
| eret!(MainErr::ConfIsNull) | ||
| eret!(StartupResultCode::InvalidParams, "Configuration is null") | ||
| } | ||
| let conf = CStr::from_ptr(conf); | ||
| let conf = match conf.to_str() { | ||
| let conf_cstr = CStr::from_ptr(conf); | ||
| let conf_str = match conf_cstr.to_str() { | ||
| Ok(s) => s, | ||
| Err(e) => eret!(MainErr::ConfNotUtf8, e), | ||
| Err(e) => eret!( | ||
| StartupResultCode::InvalidParams, | ||
| format!("Configuration is not valid UTF-8: {}", e) | ||
| ), | ||
| }; | ||
|
|
||
| let conf: json::Value = match json::from_str(conf_str) { | ||
| Ok(v) => v, | ||
| Err(e) => eret!( | ||
| StartupResultCode::ConfigError, | ||
| format!("Failed to parse configuration: {}", e) | ||
| ), | ||
| }; | ||
| let conf = conf.to_owned(); | ||
|
|
||
| if LP_MAIN_RUNNING.load(Ordering::Relaxed) { | ||
| eret!(StartupResultCode::AlreadyRunning, "MM2 is already running"); | ||
| } | ||
|
|
||
| CTX.store(0, Ordering::Relaxed); // Remove the old context ID during restarts. | ||
|
|
||
| register_callback(FfiCallback::with_ffi_function(log_cb)); | ||
|
|
||
| let rc = thread::Builder::new().name("lp_main".into()).spawn(move || { | ||
| if let Err(true) = LP_MAIN_RUNNING.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) { | ||
| log!("lp_main already started!"); | ||
| return; | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't we propagate this as an error back to the caller? do we?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done f61bac7 |
||
|
|
||
| let ctx_cb = &|ctx| CTX.store(ctx, Ordering::Relaxed); | ||
| match catch_unwind(move || mm2_main::run_lp_main(Some(&conf), ctx_cb, KDF_VERSION.into(), KDF_DATETIME.into())) | ||
| { | ||
| Ok(Ok(_)) => log!("run_lp_main finished"), | ||
| Ok(Err(err)) => log!("run_lp_main error: {}", err), | ||
| Err(err) => log!("run_lp_main panic: {:?}", any_to_str(&*err)), | ||
|
|
||
| match catch_unwind(move || { | ||
| let params = LpMainParams::with_conf(conf).log_filter(None); | ||
|
|
||
| match block_on(mm2_main::lp_main( | ||
| params, | ||
| &ctx_cb, | ||
| KDF_VERSION.into(), | ||
| KDF_DATETIME.into(), | ||
| )) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also errors from
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done f61bac7 |
||
| Ok(ctx) => { | ||
| if let Err(e) = block_on(mm2_main::lp_run(ctx)) { | ||
| log!("MM2 runtime error: {}", e); | ||
| } | ||
| }, | ||
| Err(e) => log!("MM2 initialization failed: {}", e), | ||
| } | ||
| }) { | ||
| Ok(_) => log!("MM2 thread completed normally"), | ||
| Err(err) => log!("MM2 thread panicked: {:?}", any_to_str(&*err)), | ||
| }; | ||
|
|
||
| LP_MAIN_RUNNING.store(false, Ordering::Relaxed) | ||
| }); | ||
|
|
||
| if let Err(e) = rc { | ||
| eret!(MainErr::CantThread, e) | ||
| LP_MAIN_RUNNING.store(false, Ordering::Relaxed); | ||
| eret!( | ||
| StartupResultCode::SpawnError, | ||
| format!("Failed to spawn MM2 thread: {:?}", e) | ||
| ); | ||
| } | ||
| MainErr::Ok as i8 | ||
|
|
||
| StartupResultCode::Ok as i8 | ||
| } | ||
|
|
||
| /// Checks if the MM2 singleton thread is currently running or not. | ||
|
|
@@ -109,7 +136,7 @@ pub extern "C" fn mm2_test(torch: i32, log_cb: extern "C" fn(line: *const c_char | |
| static RUNNING: AtomicBool = AtomicBool::new(false); | ||
| if let Err(true) = RUNNING.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) { | ||
| log!("mm2_test] Running already!"); | ||
| return -1; | ||
| return StartupResultCode::AlreadyRunning as i32; | ||
| } | ||
|
|
||
| // #402: Stop the MM in order to test the library restart. | ||
|
|
@@ -120,7 +147,7 @@ pub extern "C" fn mm2_test(torch: i32, log_cb: extern "C" fn(line: *const c_char | |
| Ok(ctx) => ctx, | ||
| Err(err) => { | ||
| log!("mm2_test] Invalid CTX? !from_ffi_handle: {}", err); | ||
| return -1; | ||
| return StartupResultCode::InvalidParams as i32; | ||
| }, | ||
| }; | ||
| let conf = json::to_string(&ctx.conf).unwrap(); | ||
|
|
@@ -177,10 +204,10 @@ pub extern "C" fn mm2_test(torch: i32, log_cb: extern "C" fn(line: *const c_char | |
| log!("mm2_test] Restarting MM…"); | ||
| let conf = CString::new(&conf[..]).unwrap(); | ||
| let rc = unsafe { mm2_main(conf.as_ptr(), log_cb) }; | ||
| let rc = MainErr::from_i8(rc).unwrap(); | ||
| if rc != MainErr::Ok { | ||
| let rc = StartupResultCode::from_i8(rc).unwrap(); | ||
| if rc != StartupResultCode::Ok { | ||
| log!("!mm2_main: {:?}", rc); | ||
| return -1; | ||
| return rc as i32; | ||
| } | ||
|
|
||
| // Wait for the new MM instance to allocate context. | ||
|
|
@@ -192,14 +219,14 @@ pub extern "C" fn mm2_test(torch: i32, log_cb: extern "C" fn(line: *const c_char | |
| } | ||
| if now_float() - since > 60.0 { | ||
| log!("mm2_test] Won't start"); | ||
| return -1; | ||
| return StartupResultCode::InitError as i32; | ||
| } | ||
| } | ||
|
|
||
| let ctx_id = CTX.load(Ordering::Relaxed); | ||
| if ctx_id == prev_ctx_id { | ||
| log!("mm2_test] Context ID is the same"); | ||
| return -1; | ||
| return StartupResultCode::InvalidParams as i32; | ||
| } | ||
| log!("mm2_test] New MM instance {} started", ctx_id); | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.