summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Fitzgerald <fitzgen@gmail.com>2016-12-21 16:07:09 -0800
committerNick Fitzgerald <fitzgen@gmail.com>2016-12-21 16:07:09 -0800
commit3fa229919196d2be4610b2e2f84d0f05f0be8c09 (patch)
treeb9420aab8d22344444d75d5378b18fe38c2aa69a
parent96e5d770eccb9b56b01aa1fd30e04e885d107ad0 (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.rs34
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) {