-
Notifications
You must be signed in to change notification settings - Fork 307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cbindgen panicks when parse-expand is run inside of buildscript due to inability to acquire semaphore #347
Comments
Do you know if this is a regression? |
This was the first time I used |
I ran into [#347] on a different repository. I now tried to reproduce it with a minimal example. The problem seems to have to do with locking files. Even if you let the expansion happen in a different directory, there seems to be a locking deadlock. ```console $ lslocks|grep cargo cargo 10199 FLOCK WRITE 0 0 0 /home/vmx/src/rust/cbindgen/hello/target/debug/.carg -lock cargo 12301 FLOCK WRITE* 0 0 0 /home/vmx/src/rust/cbindgen/hello/expanded/debug/.cargo-lock cargo 10204 FLOCK WRITE 0 0 0 /home/vmx/src/rust/cbindgen/hello/expanded/debug/.cargo-lock ``` Process 12301 tries to get the lock, but can't. This is easily repoducible with this repo. Just run it like that: ```console $ CARGO_EXPAND_TARGET_DIR=./expanded cargo build … Compiling cbindgen-expand-bug v0.1.0 (/home/vmx/src/rust/cbindgen/cbindgen-expand-bug) Building [====================================================> ] 101/103: cbindgen-expand-bug(build) ``` This will then start to hang. You can now check the file locks as outlined above. [#347]: mozilla/cbindgen#347
I ran into [#347] on a different repository. I now tried to reproduce it with a minimal example. The problem seems to have to do with locking files. Even if you let the expansion happen in a different directory, there seems to be a locking deadlock. ```console $ lslocks|grep cargo cargo 10199 FLOCK WRITE 0 0 0 /home/vmx/src/rust/cbindgen/hello/target/debug/.carg -lock cargo 12301 FLOCK WRITE* 0 0 0 /home/vmx/src/rust/cbindgen/hello/expanded/debug/.cargo-lock cargo 10204 FLOCK WRITE 0 0 0 /home/vmx/src/rust/cbindgen/hello/expanded/debug/.cargo-lock ``` Process 12301 tries to get the lock, but can't. This is easily repoducible with this repo. Just run it like that: ```console $ CARGO_EXPAND_TARGET_DIR=./expanded cargo build … Compiling cbindgen-expand-bug v0.1.0 (/home/vmx/src/rust/cbindgen/cbindgen-expand-bug) Building [====================================================> ] 101/103: cbindgen-expand-bug(build) ``` You can now start to watch the locks: ```console $ watch 'lslocks|grep cargo Every 2.0s: lslocks|grep cargo gene: Fri Jun 28 17:16:15 2019 cargo 29961 FLOCK WRITE* 0 0 0 /tmp/cbindgen-expand-bug/expanded/debug/.cargo-lock cargo 27746 FLOCK WRITE 0 0 0 /tmp/cbindgen-expand-bug/expanded/debug/.cargo-lock cargo 25472 FLOCK WRITE 0 0 0 /tmp/cbindgen-expand-bug/target/debug/.cargo-lock ``` In the beginning you will only see a `WRITE` lock on the `target` directory. Next will be the lock on `expanded` and finally a second `WRITE` lock will appear on expanded. [#347]: mozilla/cbindgen#347
I also ran into this issue. I created a minimal example for this problem at https://github.com/vmx/cbindgen-expand-bug. I hope it helps fixing the bug. Here's the summary about what I found out: I now tried to reproduce it with a minimal example. The problem seems to have to do with locking files. Even if you let the expansion happen in a different directory, there seems to be a locking deadlock. $ lslocks|grep cargo
cargo 10199 FLOCK WRITE 0 0 0 /home/vmx/src/rust/cbindgen/hello/target/debug/.carg -lock
cargo 12301 FLOCK WRITE* 0 0 0 /home/vmx/src/rust/cbindgen/hello/expanded/debug/.cargo-lock
cargo 10204 FLOCK WRITE 0 0 0 /home/vmx/src/rust/cbindgen/hello/expanded/debug/.cargo-lock Process 12301 tries to get the lock, but can't. This is easily repoducible with this repo. Just run it like that: $ CARGO_EXPAND_TARGET_DIR=./expanded cargo build
…
Compiling cbindgen-expand-bug v0.1.0 (/home/vmx/src/rust/cbindgen/cbindgen-expand-bug)
Building [====================================================> ] 101/103: cbindgen-expand-bug(build) You can now start to watch the locks: $ watch 'lslocks|grep cargo
Every 2.0s: lslocks|grep cargo gene: Fri Jun 28 17:16:15 2019
cargo 29961 FLOCK WRITE* 0 0 0 /tmp/cbindgen-expand-bug/expanded/debug/.cargo-lock
cargo 27746 FLOCK WRITE 0 0 0 /tmp/cbindgen-expand-bug/expanded/debug/.cargo-lock
cargo 25472 FLOCK WRITE 0 0 0 /tmp/cbindgen-expand-bug/target/debug/.cargo-lock In the beginning you will only see a |
I'm getting closer. The problem is when cbindgen is called from build.rs. When you want to expand such a crate it will call I tried to fix it like this: diff --git a/src/bindgen/cargo/cargo_expand.rs b/src/bindgen/cargo/cargo_expand.rs
index 905fc80..5c1a58e 100644
--- a/src/bindgen/cargo/cargo_expand.rs
+++ b/src/bindgen/cargo/cargo_expand.rs
@@ -77,6 +77,10 @@ pub fn expand(
cmd.env("CARGO_TARGET_DIR", path);
}
+ // Set this variable so that we don't call it recursively if we expand a crate that is using
+ // cbindgen
+ cmd.env("_CBINDGEN_IS_RUNNING", "1");
+
cmd.arg("rustc");
cmd.arg("--lib");
cmd.arg("--manifest-path");
diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs
index a7cd618..bfa4c21 100644
--- a/src/bindgen/parser.rs
+++ b/src/bindgen/parser.rs
@@ -179,6 +179,13 @@ impl<'a> Parser<'a> {
fn parse_expand_crate(&mut self, pkg: &PackageRef) -> Result<(), Error> {
assert!(self.lib.is_some());
+ // If you want to expand the crate you run cbindgen on you might end up in an endless
+ // recursion if the cbindgen generation is triggered from build.rs. Hence don't run the
+ // expansion if the build was already triggered by cbindgen.
+ if std::env::var("_CBINDGEN_IS_RUNNING").is_ok() {
+ return Ok(());
+ }
+
let mod_parsed = {
if !self.cache_expanded_crate.contains_key(&pkg.name) {
let s = self This is already pretty close. It works well if you have So if anyone has a better idea on how to make sure that cbindgen isn't running itself again, that would be great. BTW: It's not a regression I'm able to reproduce it down to version 0.2 easily. |
The patch above combined with this patch --- a/src/bindgen/cargo/cargo_expand.rs
+++ b/src/bindgen/cargo/cargo_expand.rs
@@ -6,7 +6,7 @@ use std::env;
use std::error;
use std::fmt;
use std::io;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::{from_utf8, Utf8Error};
@@ -75,6 +75,11 @@ pub fn expand(
cmd.env("CARGO_TARGET_DIR", _temp_dir.unwrap().path());
} else if let Ok(ref path) = env::var("CARGO_EXPAND_TARGET_DIR") {
cmd.env("CARGO_TARGET_DIR", path);
+ } else {
+ // Don't use the default dir, else we could end up in a deadlock cbindgen is run from
+ // a build.rs file
+ let out_dir = PathBuf::from(&env::var("OUT_DIR").unwrap());
+ cmd.env("CARGO_TARGET_DIR", out_dir.join("expanded"));
}
// Set this variable so that we don't call it recursively if we expand a crate that is using make the build at least pass. I still need to confirm if it actually does the right thing. |
When crates should get expanded, then cargo is run again from within cbindgen. When cbindgen is started from a build.rs file, this means that cargo is starting another cargo run. Cargo locks the directory it is running on. If two cargos spawn by each other run with the same target directory, then they both want to accquire a lock and hence deadlock. This commit fixes the problem with running the spawned cargo at a different directory. Please note that this will always be the same directory, hence any subsequent runs will be faster (as you would exepct it to be). This is part of mozilla#347.
To expand a crate, cbindgen calls cargo on that crate. cbindgen can be called from a build.rs file. But if cargo is called again, it will also call cbindgen again and hence end up in an endless recursion. This commit makes sure that cbindgen isn't called again if it is already running. You can verify this fix with this minimal example https://github.com/vmx/cbindgen-expand-bug Fixes mozilla#347.
When crates should get expanded, then cargo is run again from within cbindgen. When cbindgen is started from a build.rs file, this means that cargo is starting another cargo run. Cargo locks the directory it is running on. If two cargos spawn by each other run with the same target directory, then they both want to accquire a lock and hence deadlock. This commit fixes the problem with running the spawned cargo at a different directory. Please note that this will always be the same directory, hence any subsequent runs will be faster (as you would exepct it to be). This is part of mozilla#347.
To expand a crate, cbindgen calls cargo on that crate. cbindgen can be called from a build.rs file. But if cargo is called again, it will also call cbindgen again and hence end up in an endless recursion. This commit makes sure that cbindgen isn't called again if it is already running. You can verify this fix with this minimal example https://github.com/vmx/cbindgen-expand-bug Fixes mozilla#347.
When crates should get expanded, then cargo is run again from within cbindgen. When cbindgen is started from a build.rs file, this means that cargo is starting another cargo run. Cargo locks the directory it is running on. If two cargos spawn by each other run with the same target directory, then they both want to accquire a lock and hence deadlock. This commit fixes the problem with running the spawned cargo at a different directory. Please note that this will always be the same directory, hence any subsequent runs will be faster (as you would exepct it to be). This is part of #347.
I have successfully run
cbingen
on the command-line using the followingcbindgen.toml
:I decided to add it as a build script:
Upon execution, of
cargo build
cbindgen instantly crashes. It seems likecbindgen
tries to acquire a lock on the build directory that was previously acquired bycargo
, and thus crashes after outputing the following:I am aware of PR #72, and as such attempted to set
CARGO_EXPAND_TARGET_DIR
, but the only change was that it took a little longer for the panick to occur.I also read PR #153 which seems to have a similar problem, except that it doesn't result in a panick.
To use
cbindgen
I swapped to nightly, as it was required for expanding macros. I am currently at:The text was updated successfully, but these errors were encountered: