Rust: Segfault beim Ausführen einer bestimmten Codezeile aus einer dynamisch geladenen Bibliothek

Ich schreibe ein einfaches Plugin-basiertes System in Rust, um einige Kenntnisse und Erfahrungen im Umgang mit der Sprache zu sammeln. Mein System lädt Bibliotheken dynamisch und führt sie zur Laufzeit aus, um jedes Plugin zu initialisieren. Beim Ausführen von Code aus einer dynamisch geladenen Bibliothek stößt ich auf ein interessantes Problem mit Segfault.

Dies ist der Code zum Laden und Ausführen der Plugin-Init-Funktion: (dieses Bit funktioniert einwandfrei)

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);
}

Dies ist die Init-Funktion in der Plugin-Bibliothek:

#[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.");
}

Wie bereits erwähnt, tritt der Segfault in der register_plugin-Funktion der PluginSystem-Struktur mit dem Namen ps auf. Diese Struktur ist der aufrufenden Methode entlehnt (im ersten Codeabschnitt).

Dies ist die Funktion register_plugin im PluginSystem:

pub fn register_plugin(&mut self, plugin_name: &'s str)
{
    if ! self.plugins.contains_key(&plugin_name) {
        let hm = HashMap::new(); //<-- Segfault Here
        self.plugins.insert(plugin_name, hm);
    };
}

Der Segfault tritt auf, wenn @ ausgeführt wiHashMap::new() in diesem Codeblock;

Ich habe versucht, diese Funktion anders zu implementieren, wie in:

pub fn register_plugin(&mut self, plugin_name: &'s str)
{
    match self.plugins.entry(plugin_name) {
                Vacant(entry) => {
                        entry.set(HashMap::new()); //<-- Segfault Here
                    }
                Occupied(mut entry) => {  }
            }
}

Aber ich bekomme genau das gleiche Problem.

Wenn ich die Funktion register_plugin überspringe und anderen Code in der dynamisch geladenen Bibliothek ausführe, funktioniert dies einwandfrei. Tatsächlich ist der einzige Code, auf dem diese Standardeinstellung angewendet wird,HashMap::new().

Ist das ein Fehler oder ein vorhandenes Problem, oder mache ich etwas falsch?

Mehr Info: Ich habe Rust mit Debugging-Symbolen kompiliert, um den HashMap-Code durchzugehen und das Problem zu finden. Es sieht so aus, als würde es nicht einmal versuchen, die new () -Funktion auszuführen, wenn man den Code debuggt oder in @ gehHashMap::new() der Debugger springt direkt zu dieser Funktion in unwind.rs

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; //<-- Steps into this line
        rtdebug!("caught {}", (*my_ep).uwe.exception_class);
        let cause = (*my_ep).cause.take(); //<-- Segfaults Here
        uw::_Unwind_DeleteException(ep);
        Err(cause.unwrap())
    };

Der Segfault tritt im @ acause.take() Funktion, ich denke, es liegt daran, dass my_ep.cause null oder nicht zugreifbar ist. Es wird also eine ungültige Ausnahme generiert, undtryie @ -Funktion verschluckt sich daran und gibt den Segfault aus. Dies hängt damit zusammen, dass der HashMap-Code aus der dynamisch geladenen Bibliothek aufgerufen wird, aber ich weiß nicht, wie er zusammenhängt.

ielen Dank für jede Hilf

EDIT: Meine Plattform ist Linux x64, ich verwende einen frisch gebauten Rost von Git Master ab gestern (28. Oktober '14).

Antworten auf die Frage(1)

Ihre Antwort auf die Frage