From 3e4b49886d0a675a202b3968aba8167f69d584b2 Mon Sep 17 00:00:00 2001 From: Serious <121734574+seriouscatsoserious@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:19:37 -0600 Subject: [PATCH] Implement `ctrlc` in place of `signal-hook` on Windows (#1123) * Implement ctrlc for Windows * Add Windows CI workflow * Fix unused import on Windows by conditionally importing spawn * Pin ctrlc to =3.4.2 for Debian stable compatibility --- .github/workflows/rust.yml | 9 ++++++--- Cargo.lock | 22 ++++++++++++++++++++++ Cargo.toml | 7 ++++++- src/signals.rs | 26 ++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 80d87b0d6..5f3da2666 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -10,16 +10,19 @@ jobs: build: name: Build - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: matrix: + os: [ubuntu-latest, windows-latest] build-args: [ --locked --no-default-features, - --locked, - --locked --features metrics_process, + --locked ] + include: + - os: ubuntu-latest + build-args: --locked --features metrics_process steps: - uses: actions/checkout@v3 diff --git a/Cargo.lock b/Cargo.lock index ded97d32b..c7456e5b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,6 +349,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctrlc" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" +dependencies = [ + "nix", + "windows-sys 0.52.0", +] + [[package]] name = "digest" version = "0.10.7" @@ -398,6 +408,7 @@ dependencies = [ "configure_me", "configure_me_codegen", "crossbeam-channel", + "ctrlc", "dirs-next", "electrs-rocksdb", "env_logger", @@ -721,6 +732,17 @@ dependencies = [ "serde_json", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "libc", +] + [[package]] name = "nom" version = "7.1.3" diff --git a/Cargo.toml b/Cargo.toml index be01ee09f..65f9158b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,9 +36,14 @@ rayon = "1.9" serde = "1.0" serde_derive = "1.0, <=1.0.171" # avoid precompiled binaries (https://github.com/serde-rs/serde/issues/2538) serde_json = "1.0" -signal-hook = "0.3" tiny_http = { version = "0.12", optional = true } +[target.'cfg(windows)'.dependencies] +ctrlc = "=3.4.2" + +[target.'cfg(not(windows))'.dependencies] +signal-hook = "0.3" + [dependencies.electrs-rocksdb] version = "0.19.0-e3" diff --git a/src/signals.rs b/src/signals.rs index 53c08fa10..f96aca1f5 100644 --- a/src/signals.rs +++ b/src/signals.rs @@ -1,6 +1,9 @@ +#[cfg(not(windows))] use anyhow::Context; use crossbeam_channel::{unbounded, Receiver}; +#[cfg(not(windows))] use signal_hook::consts::signal::*; +#[cfg(not(windows))] use signal_hook::iterator::Signals; use std::sync::{ @@ -9,6 +12,7 @@ use std::sync::{ }; use std::{error, fmt}; +#[cfg(not(windows))] use crate::thread::spawn; #[derive(Debug)] @@ -53,6 +57,7 @@ pub(crate) struct Signal { } impl Signal { + #[cfg(not(windows))] pub fn new() -> Signal { let ids = vec![ SIGINT, SIGTERM, @@ -80,6 +85,27 @@ impl Signal { result } + #[cfg(windows)] + pub fn new() -> Signal { + let (tx, rx) = unbounded(); + let result = Signal { + rx, + exit: ExitFlag::new(), + }; + + let exit_flag = result.exit.clone(); + + // Handle Ctrl-C + ctrlc::set_handler(move || { + info!("notified via Ctrl-C"); + exit_flag.set(); + let _ = tx.send(()); + }) + .expect("failed to set Ctrl-C handler"); + + result + } + pub fn receiver(&self) -> &Receiver<()> { &self.rx }