git2-rs icon indicating copy to clipboard operation
git2-rs copied to clipboard

Runtime loading the library causes unwanted behavior after unload

Open DmitryDodzin opened this issue 3 years ago • 0 comments

Hi so I used libloading crate to load a plugin for my code that depends on git2 Once a Repository object was created at least once (even if dropped instantly) during the run of the app upon exit the process closes with:

error: process didn't exit successfully: `target\release\cargo-mol.exe --plugins=target/release/mol_git.dll add` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

I've checked and loading and unloading the plugin code with different dependencies and the process behaves fine no errors *checked with nalgebra and openssl

I'm not sure how to diagnose the problem deeper don't quite have the experience for it

usage

fn on_load(&mut self) {
    self.repo = Repository::open(DEFAULT_PACKAGE_DIR.as_path()).ok();
}

the exit error happens even if dropped instantly

fn on_load(&mut self) {
    drop(Repository::open("."))
}

plugin loading & unloading

impl PluginManager {
  /// # Safety
  ///
  /// This function opens a compiled cdylib and thus should not be called on cdylib that doesn't implement declare_plugin! macro
  pub unsafe fn load<P: AsRef<OsStr>>(&mut self, library_path: P) -> anyhow::Result<()> {
    let library = Rc::new(Library::new(library_path)?);

    let decl = library
      .get::<*mut PluginDeclaration>(b"plugin_declaration\0")?
      .read();

    // version checks to prevent accidental ABI incompatibilities
    if decl.rustc_version != RUSTC_VERSION || decl.core_version != CORE_VERSION {
      return Err(PluginLoadError::IncompatibleVersion.into());
    }

    let mut registrar = PluginRegistrar::new(Rc::clone(&library));

    (decl.register)(&mut registrar);

    self.plugins.extend(registrar.consume());
    self.libraries.push(library);

    Ok(())
  }
}

impl Drop for PluginManager {
  fn drop(&mut self) {
    for mut plugin in self.plugins.drain(..) {
      plugin.on_unload();
    }

    for library in self.libraries.drain(..) {
      drop(library);
    }
  }
}

**checked and Rc for Library is at 1 strong 0 weak before being dropped

DmitryDodzin avatar Dec 08 '21 12:12 DmitryDodzin