diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2016-12-21 16:07:09 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2016-12-21 16:07:09 -0800 |
commit | 3fa229919196d2be4610b2e2f84d0f05f0be8c09 (patch) | |
tree | b9420aab8d22344444d75d5378b18fe38c2aa69a | |
parent | 96e5d770eccb9b56b01aa1fd30e04e885d107ad0 (diff) |
Ensure that we only load `libclang` once across all threads, and that it is not prematurely dropped.
Honestly, I'm still not 100% sure what the root cause of the Clang and
LLVM issues I was seeing were, but when I ensure that we only have one
libclang loaded across all threads and that it is never dropped, the
assertions go away.
Fixes #350.
-rw-r--r-- | libbindgen/src/lib.rs | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/libbindgen/src/lib.rs b/libbindgen/src/lib.rs index 4ef8b54c..5bec0406 100644 --- a/libbindgen/src/lib.rs +++ b/libbindgen/src/lib.rs @@ -87,6 +87,7 @@ use std::collections::HashSet; use std::fs::OpenOptions; use std::io::{self, Write}; use std::path::Path; +use std::sync::{Arc, Mutex}; use syntax::ast; use syntax::codemap::{DUMMY_SP, Span}; @@ -495,6 +496,34 @@ pub enum LinkType { Framework, } +fn ensure_libclang_is_loaded() { + if clang_sys::is_loaded() { + return; + } + + // XXX (issue #350): Ensure that our dynamically loaded `libclang` + // doesn't get dropped prematurely, nor is loaded multiple times + // across different threads. + + lazy_static! { + static ref LIBCLANG: Mutex<Option<Arc<clang_sys::SharedLibrary>>> = { + Mutex::new(None) + }; + } + + let mut libclang = LIBCLANG.lock().unwrap(); + if !clang_sys::is_loaded() { + if libclang.is_none() { + // TODO(emilio): Return meaningful error (breaking). + clang_sys::load().expect("Unable to find libclang"); + *libclang = Some(clang_sys::get_library() + .expect("We just loaded libclang and it had better still be here!")); + } else { + clang_sys::set_library(libclang.clone()); + } + } +} + /// Generated Rust bindings. #[derive(Debug)] pub struct Bindings<'ctx> { @@ -511,10 +540,7 @@ impl<'ctx> Bindings<'ctx> { span: Option<Span>) -> Result<Bindings<'ctx>, ()> { let span = span.unwrap_or(DUMMY_SP); - if !clang_sys::is_loaded() { - // TODO(emilio): Return meaningful error (breaking). - clang_sys::load().expect("Unable to find libclang"); - } + ensure_libclang_is_loaded(); // TODO: Make this path fixup configurable? if let Some(clang) = clang_sys::support::Clang::find(None) { |