diff options
-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) { |