diff --git a/Cargo.lock b/Cargo.lock index 00681410..d12ba165 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -142,6 +142,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + [[package]] name = "color-eyre" version = "0.6.3" @@ -336,9 +342,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.183" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "linux-raw-sys" @@ -376,6 +382,18 @@ dependencies = [ "adler", ] +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -757,6 +775,7 @@ name = "thrust" version = "0.1.0" dependencies = [ "anyhow", + "nix", "pretty", "process_control", "tempfile", diff --git a/Cargo.toml b/Cargo.toml index 8aa6b979..e1f18a0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ thiserror = "2.0.18" tracing = "0.1.44" tracing-subscriber = { version = "0.3.23", features = ["env-filter"] } process_control = "5.2.0" +nix = { version = "0.31.3", default-features = false, features = ["signal"] } [dev-dependencies] ui_test = "0.30.6" diff --git a/src/chc/solver.rs b/src/chc/solver.rs index 5792d756..78f09589 100644 --- a/src/chc/solver.rs +++ b/src/chc/solver.rs @@ -52,13 +52,20 @@ impl CommandConfig { use process_control::{ChildExt as _, Control as _}; let start = std::time::Instant::now(); - tracing::info!(timeout = ?self.timeout, pid = child.id(), "waiting"); - let mut child = child.controlled_with_output().terminate_for_timeout(); + let pid = child.id(); + tracing::info!(timeout = ?self.timeout, pid, "waiting"); + let mut child = child.controlled_with_output(); if let Some(timeout) = self.timeout { child = child.time_limit(timeout); } let output = match child.wait()? { - None => return Err(CheckSatError::Timeout(self.timeout.unwrap())), + None => { + let pid = nix::unistd::Pid::from_raw(pid as i32); + if let Err(err) = nix::sys::signal::kill(pid, nix::sys::signal::Signal::SIGTERM) { + tracing::error!(?pid, ?err, "failed to send SIGTERM to solver process"); + } + return Err(CheckSatError::Timeout(self.timeout.unwrap())); + } Some(output) => output, }; let elapsed = std::time::Instant::now() - start; diff --git a/tests/thrust-pcsat-wrapper b/tests/thrust-pcsat-wrapper index 448b0ea5..756c0ca9 100755 --- a/tests/thrust-pcsat-wrapper +++ b/tests/thrust-pcsat-wrapper @@ -3,12 +3,19 @@ COAR_IMAGE=${COAR_IMAGE:-ghcr.io/hiroshi-unno/coar:main} smt2=$(mktemp -p . --suffix .smt2) -trap "rm -f $smt2" EXIT +solver_out=$(mktemp) +trap 'rm -f "$smt2" "$solver_out"' EXIT cp "$1" "$smt2" -out=$( -docker run --rm -v "$PWD:/mnt" -w /root/coar "$COAR_IMAGE" \ - main.exe -c ./config/solver/pcsat_tbq_ar.json -p pcsp "/mnt/$smt2" -) + +container=$(docker create --rm -v "$PWD:/mnt" -w /root/coar "$COAR_IMAGE" \ + main.exe -c ./config/solver/pcsat_tbq_ar.json -p pcsp "/mnt/$smt2") +trap 'docker rm --force "$container" >/dev/null; exit 143' TERM + +# needs `wait` to fire the `trap` above +docker start --attach "$container" > "$solver_out" & +wait $! exit_code=$? + +out=$(< "$solver_out") echo "${out%,*}" exit "$exit_code"