forked from 1b-agent/opencadstudio-upstream
feat(plugin): wrap external-plugin calls in a panic guard
A buggy external plugin that panicked anywhere — during load (version, register, manifest), during ribbon build / dispatch, or inside an interactive command (prompt, on_point, on_enter, on_object_pick) — took the host down with it (#134). Run every cdylib entry point under catch_unwind so the host stays up: the plugin's call is treated as inert (load fails, dispatch returns "didn't handle it", interactive hooks resolve to Cancel) and a "Plugin <hook> panicked: …" line lands in the command line on the next tick. (#145) Scope is Rust panics across the cdylib boundary, not genuine UB — real isolation (segfault-proof) still requires out-of-process plugins. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
2a260be31d
commit
f860fb39c2
5 files changed
+122
-14
No files matched your search
+10
-3
@@ -311,7 +311,10 @@ mod loader {
|
||||
let version: libloading::Symbol<extern "C" fn() -> u32> = lib
|
||||
.get(b"ocs_plugin_api_version")
|
||||
.map_err(|_| "missing ocs_plugin_api_version symbol".to_string())?;
|
||||
let v = version();
|
||||
// Wrap the version + register calls in a panic guard so a plugin
|
||||
// that panics during load can't take down the host. (#145)
|
||||
let v = crate::plugin::guard("version", || version())
|
||||
.ok_or_else(|| "ocs_plugin_api_version panicked".to_string())?;
|
||||
if v != ocs_plugin_api::API_VERSION {
|
||||
return Err(format!(
|
||||
"API version {v} != host {}",
|
||||
@@ -324,12 +327,16 @@ mod loader {
|
||||
> = lib
|
||||
.get(b"ocs_plugin_register")
|
||||
.map_err(|_| "missing ocs_plugin_register symbol".to_string())?;
|
||||
let raw = register();
|
||||
let raw = crate::plugin::guard("register", || register())
|
||||
.ok_or_else(|| "ocs_plugin_register panicked".to_string())?;
|
||||
if raw.is_null() {
|
||||
return Err("ocs_plugin_register returned null".into());
|
||||
}
|
||||
let plugin = *Box::from_raw(raw);
|
||||
let id = plugin.manifest().id.to_string();
|
||||
// The manifest read happens once at load; guard it too — a buggy
|
||||
// manifest() that panics here would otherwise crash startup. (#145)
|
||||
let id = crate::plugin::guard("manifest", || plugin.manifest().id.to_string())
|
||||
.ok_or_else(|| "plugin manifest() panicked".to_string())?;
|
||||
Ok(LoadedPlugin {
|
||||
plugin,
|
||||
_lib: lib,
|
||||
|
||||
Reference in new issue
Block a user