Rust: Segfault ao executar linha de código específica de uma biblioteca carregada dinamicamente
Estou escrevendo um sistema simples baseado em plugins no Rust para obter algumas habilidades e experiência no uso da linguagem. Meu sistema carrega bibliotecas dinamicamente e as executa em tempo de execução para inicializar cada plug-in. Estou com um problema interessante de segfault ao executar código de uma biblioteca carregada dinamicamente.
Este é o código para carregar e executar a função init do plugin: (este bit funciona bem)
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);
}
Esta é a função init na biblioteca de plug-ins:
#[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.");
}
Conforme comentado, o segfault ocorre na função register_plugin da estrutura PluginSystem denominada ps. Essa estrutura é emprestada do método de chamada (no primeiro bloco de código).
Esta é a função register_plugin no 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);
};
}
O segfault ocorre ao executarHashMap::new()
neste bloco de código;
Eu tentei implementar essa função de maneira diferente, como em:
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) => { }
}
}
Mas eu recebo exatamente o mesmo problema.
Se eu pular a função register_plugin e executar outro código na biblioteca carregada dinamicamente, ela funcionará bem. De fato, o único código no qual este segmento éHashMap::new()
.
Isso é um bug ou um problema existente ou estou fazendo algo errado?
Mais informações: Eu compilei ferrugem com símbolos de depuração para percorrer o código HashMap para encontrar o problema. Parece que nem tenta executar a função new (), ao depurar o código, ao entrar emHashMap::new()
o depurador avança diretamente para esta função em 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())
};
O Segfault ocorre nocause.take()
função, acho que é porque my_ep.cause é nulo ou inacessível. Então, algo está gerando uma exceção inválida etry
A função está sufocando e dando o segfault. Isso está relacionado à chamada do código HashMap da biblioteca carregada dinamicamente, mas não sei como ele está relacionado.
Obrigado por qualquer ajuda.
EDIT: Minha plataforma é linux x64, estou usando uma ferrugem recém-construída do git master a partir de ontem (28 de outubro de 14).