I am writing a simple system with plugins in Rust to get some language skills and experience. My system dynamically loads libraries and executes them at runtime to initialize each plugin. Im triggering an interesting segfault problem when executing code from a dynamically loaded library.
This is the code to load and run the plugin initialization function: (this bit works fine)
pub fn register_plugins<'rp>(&'rp mut self) { let p1 = match DynamicLibrary::open(Some("librust_plugin_1.so")) { Ok(lib) => lib, Err(error) => fail!("Could not load the library: {}", error) }; let s1: extern "Rust" fn(&PluginSystem) = unsafe { match p1.symbol("init") { Err(error) => fail!("Could not load function init: {}", error), Ok(init) => mem::transmute::<*mut u8, _>(init) } }; s1(&self.ps); }
This is the init function inside the plugin library:
#[no_mangle] pub fn init(ps:&mut PluginSystem) { ps.register_plugin("ps1"); //<-- Segfault is in this method ps.add_new_hook_with_closure("onLoad", "ps1", "display greeting.", 10, test1); println!("Initialized plugin."); }
As noted, segfault happens in the register_plugin function of the PluginSystem structure called ps. This structure is borrowed from the calling method (in the first block of code).
This is the register_plugin function in the PluginSystem:
pub fn register_plugin(&mut self, plugin_name: & str) { if ! self.plugins.contains_key(&plugin_name) { let hm = HashMap::new(); //<-- Segfault Here self.plugins.insert(plugin_name, hm); }; }
Segfault occurs when HashMap::new() is executed in this code block;
I tried to implement this function in different ways, as in:
pub fn register_plugin(&mut self, plugin_name: & str) { match self.plugins.entry(plugin_name) { Vacant(entry) => { entry.set(HashMap::new());
But I get the exact same problem.
If I skip the register_plugin function and run another code in a dynamically loaded library, it works fine. In fact, the only code that this segfaults is is HashMap::new() .
Is this a bug or an existing problem, or am I doing something wrong?
Additional Information: I compiled rust with debugging symbols to go through the HashMap code to find the problem. It seems that even when trying to execute the new () function while debugging the code when entering HashMap::new() debugger goes directly to this function in the unwind.rs file:
pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box<Any + Send>> { let closure: Closure = mem::transmute(f); let ep = rust_try(try_fn, closure.code as *mut c_void, closure.env as *mut c_void); return if ep.is_null() { Ok(()) } else { let my_ep = ep as *mut Exception;
Segfault occurs in the cause.take() function, I think this is because my_ep.cause is null or not available. Thus, something throws an invalid exception, and the try function suffocates and gives segfault. This is due to calling the HashMap code from a dynamically loaded library, but I do not know how this is related.
Thanks for any help.
EDIT: My platform is linux x64, im using fresh rust from git master as of yesterday (October 28 '14).