diff -Nru rust-ctrlc-3.2.3/Cargo.lock rust-ctrlc-3.4.0/Cargo.lock --- rust-ctrlc-3.2.3/Cargo.lock 1970-01-01 00:00:01.000000000 +0000 +++ rust-ctrlc-3.4.0/Cargo.lock 1970-01-01 00:00:01.000000000 +0000 @@ -3,12 +3,6 @@ version = 3 [[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -22,48 +16,118 @@ [[package]] name = "ctrlc" -version = "3.2.3" +version = "3.4.0" dependencies = [ "nix", - "winapi", + "signal-hook", + "windows-sys", ] [[package]] name = "libc" -version = "0.2.131" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "nix" -version = "0.25.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "autocfg", "bitflags", "cfg-if", "libc", + "static_assertions", +] + +[[package]] +name = "signal-hook" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-targets" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_x86_64_msvc" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff -Nru rust-ctrlc-3.2.3/Cargo.toml rust-ctrlc-3.4.0/Cargo.toml --- rust-ctrlc-3.2.3/Cargo.toml 1970-01-01 00:00:01.000000000 +0000 +++ rust-ctrlc-3.4.0/Cargo.toml 1970-01-01 00:00:01.000000000 +0000 @@ -12,7 +12,7 @@ [package] edition = "2018" name = "ctrlc" -version = "3.2.3" +version = "3.4.0" authors = ["Antti Keränen "] exclude = [ "/.travis.yml", @@ -20,7 +20,7 @@ ] description = "Easy Ctrl-C handler for Rust projects" homepage = "https://github.com/Detegr/rust-ctrlc" -documentation = "http://detegr.github.io/doc/ctrlc" +documentation = "https://detegr.github.io/doc/ctrlc" readme = "README.md" keywords = [ "ctrlc", @@ -32,34 +32,43 @@ repository = "https://github.com/Detegr/rust-ctrlc.git" [[test]] -name = "tests" -path = "src/tests.rs" +name = "main" +path = "tests/main/mod.rs" harness = false +[[test]] +name = "issue_97" +path = "tests/main/issue_97.rs" +harness = false + +[dev-dependencies.signal-hook] +version = "0.3" + [features] termination = [] [target."cfg(unix)".dependencies.nix] -version = "0.25" +version = "0.26" features = [ "fs", "signal", ] default-features = false -[target."cfg(windows)".dependencies.winapi] -version = "0.3" +[target."cfg(windows)".dependencies.windows-sys] +version = "0.48" features = [ - "consoleapi", - "handleapi", - "synchapi", - "winbase", + "Win32_Foundation", + "Win32_System_Threading", + "Win32_Security", + "Win32_System_Console", ] -[target."cfg(windows)".dev-dependencies.winapi] -version = "0.3" +[target."cfg(windows)".dev-dependencies.windows-sys] +version = "0.48" features = [ - "fileapi", - "processenv", - "winnt", + "Win32_Storage_FileSystem", + "Win32_Foundation", + "Win32_System_IO", + "Win32_System_Console", ] diff -Nru rust-ctrlc-3.2.3/Cargo.toml.orig rust-ctrlc-3.4.0/Cargo.toml.orig --- rust-ctrlc-3.2.3/Cargo.toml.orig 1973-11-29 21:33:09.000000000 +0000 +++ rust-ctrlc-3.4.0/Cargo.toml.orig 2006-07-24 01:21:28.000000000 +0000 @@ -1,9 +1,9 @@ [package] name = "ctrlc" -version = "3.2.3" +version = "3.4.0" authors = ["Antti Keränen "] description = "Easy Ctrl-C handler for Rust projects" -documentation = "http://detegr.github.io/doc/ctrlc" +documentation = "https://detegr.github.io/doc/ctrlc" homepage = "https://github.com/Detegr/rust-ctrlc" keywords = ["ctrlc", "signal", "SIGINT"] categories = ["os"] @@ -14,18 +14,26 @@ readme = "README.md" [target.'cfg(unix)'.dependencies] -nix = { version = "0.25", default-features = false, features = ["fs", "signal"]} +nix = { version = "0.26", default-features = false, features = ["fs", "signal"]} [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["consoleapi", "handleapi", "synchapi", "winbase"] } +windows-sys = { version = "0.48", features = ["Win32_Foundation", "Win32_System_Threading", "Win32_Security", "Win32_System_Console"] } [target.'cfg(windows)'.dev-dependencies] -winapi = { version = "0.3", features = ["fileapi", "processenv", "winnt"] } +windows-sys = { version = "0.48", features = ["Win32_Storage_FileSystem", "Win32_Foundation", "Win32_System_IO", "Win32_System_Console"] } [features] termination = [] [[test]] harness = false -name = "tests" -path = "src/tests.rs" +name = "main" +path = "tests/main/mod.rs" + +[[test]] +harness = false +name = "issue_97" +path = "tests/main/issue_97.rs" + +[dev-dependencies] +signal-hook = "0.3" diff -Nru rust-ctrlc-3.2.3/.cargo_vcs_info.json rust-ctrlc-3.4.0/.cargo_vcs_info.json --- rust-ctrlc-3.2.3/.cargo_vcs_info.json 1970-01-01 00:00:01.000000000 +0000 +++ rust-ctrlc-3.4.0/.cargo_vcs_info.json 1970-01-01 00:00:01.000000000 +0000 @@ -1,6 +1,6 @@ { "git": { - "sha1": "08abf10d65095dc3b4ff5025be1c312e167108a3" + "sha1": "27bddfda1daa67fbe29c7898ac574f2e5d9ea4f9" }, "path_in_vcs": "" } \ No newline at end of file diff -Nru rust-ctrlc-3.2.3/debian/changelog rust-ctrlc-3.4.0/debian/changelog --- rust-ctrlc-3.2.3/debian/changelog 2022-08-22 07:46:41.000000000 +0000 +++ rust-ctrlc-3.4.0/debian/changelog 2023-06-28 20:53:46.000000000 +0000 @@ -1,3 +1,10 @@ +rust-ctrlc (3.4.0-1) unstable; urgency=medium + + * Team upload. + * Package ctrlc 3.4.0 from crates.io using debcargo 2.6.0 + + -- Sylvestre Ledru Wed, 28 Jun 2023 22:53:46 +0200 + rust-ctrlc (3.2.3-1) unstable; urgency=medium * Team upload. diff -Nru rust-ctrlc-3.2.3/debian/control rust-ctrlc-3.4.0/debian/control --- rust-ctrlc-3.2.3/debian/control 2022-08-22 07:46:41.000000000 +0000 +++ rust-ctrlc-3.4.0/debian/control 2023-06-28 20:53:46.000000000 +0000 @@ -7,20 +7,16 @@ rustc:native , libstd-rust-dev , librust-nix-0+fs-dev , - librust-nix-0+signal-dev , - librust-winapi-0.3+consoleapi-dev , - librust-winapi-0.3+default-dev , - librust-winapi-0.3+handleapi-dev , - librust-winapi-0.3+synchapi-dev , - librust-winapi-0.3+winbase-dev + librust-nix-0+signal-dev Maintainer: Debian Rust Maintainers Uploaders: Paride Legovini , Wolfgang Silbermayr -Standards-Version: 4.5.1 +Standards-Version: 4.6.1 Vcs-Git: https://salsa.debian.org/rust-team/debcargo-conf.git [src/ctrlc] Vcs-Browser: https://salsa.debian.org/rust-team/debcargo-conf/tree/master/src/ctrlc Homepage: https://github.com/Detegr/rust-ctrlc +X-Cargo-Crate: ctrlc Rules-Requires-Root: no Package: librust-ctrlc-dev @@ -29,24 +25,19 @@ Depends: ${misc:Depends}, librust-nix-0+fs-dev, - librust-nix-0+signal-dev, - librust-winapi-0.3+consoleapi-dev, - librust-winapi-0.3+default-dev, - librust-winapi-0.3+handleapi-dev, - librust-winapi-0.3+synchapi-dev, - librust-winapi-0.3+winbase-dev + librust-nix-0+signal-dev Provides: librust-ctrlc+default-dev (= ${binary:Version}), librust-ctrlc+termination-dev (= ${binary:Version}), librust-ctrlc-3-dev (= ${binary:Version}), librust-ctrlc-3+default-dev (= ${binary:Version}), librust-ctrlc-3+termination-dev (= ${binary:Version}), - librust-ctrlc-3.2-dev (= ${binary:Version}), - librust-ctrlc-3.2+default-dev (= ${binary:Version}), - librust-ctrlc-3.2+termination-dev (= ${binary:Version}), - librust-ctrlc-3.2.3-dev (= ${binary:Version}), - librust-ctrlc-3.2.3+default-dev (= ${binary:Version}), - librust-ctrlc-3.2.3+termination-dev (= ${binary:Version}) + librust-ctrlc-3.4-dev (= ${binary:Version}), + librust-ctrlc-3.4+default-dev (= ${binary:Version}), + librust-ctrlc-3.4+termination-dev (= ${binary:Version}), + librust-ctrlc-3.4.0-dev (= ${binary:Version}), + librust-ctrlc-3.4.0+default-dev (= ${binary:Version}), + librust-ctrlc-3.4.0+termination-dev (= ${binary:Version}) Description: Easy Ctrl-C handler for Rust projects - Rust source code This package contains the source for the Rust ctrlc crate, packaged by debcargo for use with cargo and dh-cargo. diff -Nru rust-ctrlc-3.2.3/debian/copyright.debcargo.hint rust-ctrlc-3.4.0/debian/copyright.debcargo.hint --- rust-ctrlc-3.2.3/debian/copyright.debcargo.hint 2022-08-22 07:46:41.000000000 +0000 +++ rust-ctrlc-3.4.0/debian/copyright.debcargo.hint 2023-06-28 20:53:46.000000000 +0000 @@ -12,57 +12,78 @@ be correct information so you should review and fix this before uploading to the archive. -Files: ./LICENSE-APACHE +Files: LICENSE-APACHE Copyright: 2017 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them before uploading to the archive. -Files: ./examples/readme_example.rs +Files: examples/readme_example.rs Copyright: 2015 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them before uploading to the archive. -Files: ./src/lib.rs +Files: src/lib.rs Copyright: 2017 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them before uploading to the archive. -Files: ./src/platform/mod.rs +Files: src/platform/mod.rs Copyright: 2017 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them before uploading to the archive. -Files: ./src/platform/unix/mod.rs +Files: src/platform/unix/mod.rs Copyright: 2017 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them before uploading to the archive. -Files: ./src/platform/windows/mod.rs +Files: src/platform/windows/mod.rs Copyright: 2017 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them before uploading to the archive. -Files: ./src/signal.rs +Files: src/signal.rs Copyright: 2017 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them before uploading to the archive. -Files: ./src/tests.rs -Copyright: 2017 CtrlC developers +Files: tests/main/harness.rs +Copyright: 2023 CtrlC developers +License: UNKNOWN-LICENSE; FIXME (overlay) +Comment: + FIXME (overlay): These notices are extracted from files. Please review them + before uploading to the archive. + +Files: tests/main/issue_97.rs +Copyright: 2023 CtrlC developers +License: UNKNOWN-LICENSE; FIXME (overlay) +Comment: + FIXME (overlay): These notices are extracted from files. Please review them + before uploading to the archive. + +Files: tests/main/mod.rs +Copyright: 2023 CtrlC developers +License: UNKNOWN-LICENSE; FIXME (overlay) +Comment: + FIXME (overlay): These notices are extracted from files. Please review them + before uploading to the archive. + +Files: tests/main/test_signal_hook.rs +Copyright: 2023 CtrlC developers License: UNKNOWN-LICENSE; FIXME (overlay) Comment: FIXME (overlay): These notices are extracted from files. Please review them @@ -70,9 +91,9 @@ Files: debian/* Copyright: - 2018-2022 Debian Rust Maintainers - 2018-2022 Paride Legovini - 2018-2022 Wolfgang Silbermayr + 2018-2023 Debian Rust Maintainers + 2018-2023 Paride Legovini + 2018-2023 Wolfgang Silbermayr License: MIT or Apache-2.0 License: Apache-2.0 diff -Nru rust-ctrlc-3.2.3/debian/patches/disable-windows.diff rust-ctrlc-3.4.0/debian/patches/disable-windows.diff --- rust-ctrlc-3.2.3/debian/patches/disable-windows.diff 1970-01-01 00:00:00.000000000 +0000 +++ rust-ctrlc-3.4.0/debian/patches/disable-windows.diff 2023-06-28 20:53:46.000000000 +0000 @@ -0,0 +1,41 @@ +Index: ctrlc/Cargo.toml +=================================================================== +--- ctrlc.orig/Cargo.toml ++++ ctrlc/Cargo.toml +@@ -55,20 +55,20 @@ features = [ + ] + default-features = false + +-[target."cfg(windows)".dependencies.windows-sys] +-version = "0.48" +-features = [ +- "Win32_Foundation", +- "Win32_System_Threading", +- "Win32_Security", +- "Win32_System_Console", +-] ++# [target."cfg(windows)".dependencies.windows-sys] ++# version = "0.48" ++# features = [ ++# "Win32_Foundation", ++# "Win32_System_Threading", ++# "Win32_Security", ++# "Win32_System_Console", ++# ] + +-[target."cfg(windows)".dev-dependencies.windows-sys] +-version = "0.48" +-features = [ +- "Win32_Storage_FileSystem", +- "Win32_Foundation", +- "Win32_System_IO", +- "Win32_System_Console", +-] ++# [target."cfg(windows)".dev-dependencies.windows-sys] ++# version = "0.48" ++# features = [ ++# "Win32_Storage_FileSystem", ++# "Win32_Foundation", ++# "Win32_System_IO", ++# "Win32_System_Console", ++# ] diff -Nru rust-ctrlc-3.2.3/debian/patches/relax-nix.diff rust-ctrlc-3.4.0/debian/patches/relax-nix.diff --- rust-ctrlc-3.2.3/debian/patches/relax-nix.diff 2022-08-22 07:46:41.000000000 +0000 +++ rust-ctrlc-3.4.0/debian/patches/relax-nix.diff 2023-06-28 20:53:46.000000000 +0000 @@ -2,11 +2,11 @@ =================================================================== --- ctrlc.orig/Cargo.toml +++ ctrlc/Cargo.toml -@@ -40,7 +40,7 @@ harness = false +@@ -48,7 +48,7 @@ version = "0.3" termination = [] [target."cfg(unix)".dependencies.nix] --version = "0.25" +-version = "0.26" +version = "0" features = [ "fs", diff -Nru rust-ctrlc-3.2.3/debian/patches/series rust-ctrlc-3.4.0/debian/patches/series --- rust-ctrlc-3.2.3/debian/patches/series 2022-08-22 07:46:41.000000000 +0000 +++ rust-ctrlc-3.4.0/debian/patches/series 2023-06-28 20:53:46.000000000 +0000 @@ -1 +1,2 @@ relax-nix.diff +disable-windows.diff diff -Nru rust-ctrlc-3.2.3/debian/tests/control rust-ctrlc-3.4.0/debian/tests/control --- rust-ctrlc-3.2.3/debian/tests/control 2022-08-22 07:46:41.000000000 +0000 +++ rust-ctrlc-3.4.0/debian/tests/control 2023-06-28 20:53:46.000000000 +0000 @@ -1,19 +1,19 @@ -Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.2.3 --all-targets --all-features +Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.4.0 --all-targets --all-features Features: test-name=rust-ctrlc:@ -Depends: dh-cargo (>= 18), librust-winapi-0.3+default-dev, librust-winapi-0.3+fileapi-dev, librust-winapi-0.3+processenv-dev, librust-winapi-0.3+winnt-dev, @ +Depends: dh-cargo (>= 18), librust-signal-hook-0.3+default-dev, @ Restrictions: allow-stderr, skip-not-installable -Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.2.3 --all-targets +Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.4.0 --all-targets Features: test-name=librust-ctrlc-dev:default -Depends: dh-cargo (>= 18), librust-winapi-0.3+default-dev, librust-winapi-0.3+fileapi-dev, librust-winapi-0.3+processenv-dev, librust-winapi-0.3+winnt-dev, @ +Depends: dh-cargo (>= 18), librust-signal-hook-0.3+default-dev, @ Restrictions: allow-stderr, skip-not-installable -Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.2.3 --all-targets --no-default-features --features termination +Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.4.0 --all-targets --no-default-features --features termination Features: test-name=librust-ctrlc-dev:termination -Depends: dh-cargo (>= 18), librust-winapi-0.3+default-dev, librust-winapi-0.3+fileapi-dev, librust-winapi-0.3+processenv-dev, librust-winapi-0.3+winnt-dev, @ +Depends: dh-cargo (>= 18), librust-signal-hook-0.3+default-dev, @ Restrictions: allow-stderr, skip-not-installable -Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.2.3 --all-targets --no-default-features +Test-Command: /usr/share/cargo/bin/cargo-auto-test ctrlc 3.4.0 --all-targets --no-default-features Features: test-name=librust-ctrlc-dev: -Depends: dh-cargo (>= 18), librust-winapi-0.3+default-dev, librust-winapi-0.3+fileapi-dev, librust-winapi-0.3+processenv-dev, librust-winapi-0.3+winnt-dev, @ +Depends: dh-cargo (>= 18), librust-signal-hook-0.3+default-dev, @ Restrictions: allow-stderr, skip-not-installable diff -Nru rust-ctrlc-3.2.3/README.md rust-ctrlc-3.4.0/README.md --- rust-ctrlc-3.2.3/README.md 1973-11-29 21:33:09.000000000 +0000 +++ rust-ctrlc-3.4.0/README.md 2006-07-24 01:21:28.000000000 +0000 @@ -28,10 +28,6 @@ ## Handling SIGTERM and SIGHUP Add CtrlC to Cargo.toml using `termination` feature and CtrlC will handle SIGINT, SIGTERM and SIGHUP. -``` -[dependencies] -ctrlc = { version = "3.0", features = ["termination"] } -``` ## License @@ -45,3 +41,10 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions. + +## Similar crates + +There are alternatives that give you more control over the different signals and/or add async support. + +- [signal-hook](https://github.com/vorner/signal-hook) +- [tokio::signal](https://docs.rs/tokio/latest/tokio/signal/index.html) diff -Nru rust-ctrlc-3.2.3/src/error.rs rust-ctrlc-3.4.0/src/error.rs --- rust-ctrlc-3.2.3/src/error.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-ctrlc-3.4.0/src/error.rs 2006-07-24 01:21:28.000000000 +0000 @@ -24,6 +24,11 @@ impl From for Error { fn from(e: platform::Error) -> Error { + #[cfg(not(windows))] + if e == platform::Error::EEXIST { + return Error::MultipleHandlers; + } + let system_error = std::io::Error::new(std::io::ErrorKind::Other, e); Error::System(system_error) } diff -Nru rust-ctrlc-3.2.3/src/lib.rs rust-ctrlc-3.4.0/src/lib.rs --- rust-ctrlc-3.2.3/src/lib.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-ctrlc-3.4.0/src/lib.rs 2006-07-24 01:21:28.000000000 +0000 @@ -23,6 +23,7 @@ //! //! # Example //! ```no_run +//! # #[allow(clippy::needless_doctest_main)] //! use std::sync::atomic::{AtomicBool, Ordering}; //! use std::sync::Arc; //! @@ -55,9 +56,11 @@ pub use error::Error; use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Mutex; use std::thread; static INIT: AtomicBool = AtomicBool::new(false); +static INIT_LOCK: Mutex<()> = Mutex::new(()); /// Register signal handler for Ctrl-C. /// @@ -70,34 +73,67 @@ /// ``` /// /// # Warning -/// On Unix, any existing `SIGINT`, `SIGTERM` and `SIGHUP` (if termination feature is enabled) or `SA_SIGINFO` -/// posix signal handlers will be overwritten. On Windows, multiple handler routines are allowed, -/// but they are called on a last-registered, first-called basis until the signal is handled. +/// On Unix, the handler registration for `SIGINT`, (`SIGTERM` and `SIGHUP` if termination feature +/// is enabled) or `SA_SIGINFO` posix signal handlers will be overwritten. On Windows, multiple +/// handler routines are allowed, but they are called on a last-registered, first-called basis +/// until the signal is handled. +/// +/// ctrlc::try_set_handler will error (on Unix) if another signal handler exists for the same +/// signal(s) that ctrlc is trying to attach the handler to. /// /// On Unix, signal dispositions and signal handlers are inherited by child processes created via /// `fork(2)` on, but not by child processes created via `execve(2)`. /// Signal handlers are not inherited on Windows. /// /// # Errors -/// Will return an error if another `ctrlc::set_handler()` handler exists or if a -/// system error occurred while setting the handler. +/// Will return an error if a system error occurred while setting the handler. /// /// # Panics /// Any panic in the handler will not be caught and will cause the signal handler thread to stop. +pub fn set_handler(user_handler: F) -> Result<(), Error> +where + F: FnMut() + 'static + Send, +{ + init_and_set_handler(user_handler, true) +} + +/// The same as ctrlc::set_handler but errors if a handler already exists for the signal(s). /// -pub fn set_handler(mut user_handler: F) -> Result<(), Error> +/// # Errors +/// Will return an error if another handler exists or if a system error occurred while setting the +/// handler. +pub fn try_set_handler(user_handler: F) -> Result<(), Error> where - F: FnMut() -> () + 'static + Send, + F: FnMut() + 'static + Send, { - if INIT.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).map_or_else(|e| e, |a| a) { - return Err(Error::MultipleHandlers); + init_and_set_handler(user_handler, false) +} + +fn init_and_set_handler(user_handler: F, overwrite: bool) -> Result<(), Error> +where + F: FnMut() + 'static + Send, +{ + if !INIT.load(Ordering::Acquire) { + let _guard = INIT_LOCK.lock().unwrap(); + + if !INIT.load(Ordering::Relaxed) { + set_handler_inner(user_handler, overwrite)?; + INIT.store(true, Ordering::Release); + return Ok(()); + } } + Err(Error::MultipleHandlers) +} + +fn set_handler_inner(mut user_handler: F, overwrite: bool) -> Result<(), Error> +where + F: FnMut() + 'static + Send, +{ unsafe { - match platform::init_os_handler() { + match platform::init_os_handler(overwrite) { Ok(_) => {} Err(err) => { - INIT.store(false, Ordering::SeqCst); return Err(err.into()); } } diff -Nru rust-ctrlc-3.2.3/src/platform/unix/mod.rs rust-ctrlc-3.4.0/src/platform/unix/mod.rs --- rust-ctrlc-3.2.3/src/platform/unix/mod.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-ctrlc-3.4.0/src/platform/unix/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -26,9 +26,14 @@ } } -// pipe2(2) is not available on macOS, iOS or Haiku, so we need to use pipe(2) and fcntl(2) +// pipe2(2) is not available on macOS, iOS, AIX or Haiku, so we need to use pipe(2) and fcntl(2) #[inline] -#[cfg(any(target_os = "ios", target_os = "macos", target_os = "haiku"))] +#[cfg(any( + target_os = "ios", + target_os = "macos", + target_os = "haiku", + target_os = "aix" +))] fn pipe2(flags: nix::fcntl::OFlag) -> nix::Result<(RawFd, RawFd)> { use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag}; @@ -59,7 +64,12 @@ } #[inline] -#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "haiku")))] +#[cfg(not(any( + target_os = "ios", + target_os = "macos", + target_os = "haiku", + target_os = "aix" +)))] fn pipe2(flags: nix::fcntl::OFlag) -> nix::Result<(RawFd, RawFd)> { unistd::pipe2(flags) } @@ -73,7 +83,7 @@ /// Will return an error if a system error occurred. /// #[inline] -pub unsafe fn init_os_handler() -> Result<(), Error> { +pub unsafe fn init_os_handler(overwrite: bool) -> Result<(), Error> { use nix::fcntl; use nix::sys::signal; @@ -99,11 +109,14 @@ signal::SigSet::empty(), ); - #[allow(unused_variables)] let sigint_old = match signal::sigaction(signal::Signal::SIGINT, &new_action) { Ok(old) => old, Err(e) => return Err(close_pipe(e)), }; + if !overwrite && sigint_old.handler() != signal::SigHandler::SigDfl { + signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap(); + return Err(close_pipe(nix::Error::EEXIST)); + } #[cfg(feature = "termination")] { @@ -114,18 +127,27 @@ return Err(close_pipe(e)); } }; - match signal::sigaction(signal::Signal::SIGHUP, &new_action) { - Ok(_) => {} + if !overwrite && sigterm_old.handler() != signal::SigHandler::SigDfl { + signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap(); + signal::sigaction(signal::Signal::SIGTERM, &sigterm_old).unwrap(); + return Err(close_pipe(nix::Error::EEXIST)); + } + let sighup_old = match signal::sigaction(signal::Signal::SIGHUP, &new_action) { + Ok(old) => old, Err(e) => { signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap(); signal::sigaction(signal::Signal::SIGTERM, &sigterm_old).unwrap(); return Err(close_pipe(e)); } + }; + if !overwrite && sighup_old.handler() != signal::SigHandler::SigDfl { + signal::sigaction(signal::Signal::SIGINT, &sigint_old).unwrap(); + signal::sigaction(signal::Signal::SIGTERM, &sigterm_old).unwrap(); + signal::sigaction(signal::Signal::SIGHUP, &sighup_old).unwrap(); + return Err(close_pipe(nix::Error::EEXIST)); } } - // TODO: Maybe throw an error if old action is not SigDfl. - Ok(()) } diff -Nru rust-ctrlc-3.2.3/src/platform/windows/mod.rs rust-ctrlc-3.4.0/src/platform/windows/mod.rs --- rust-ctrlc-3.2.3/src/platform/windows/mod.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-ctrlc-3.4.0/src/platform/windows/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -9,24 +9,24 @@ use std::io; use std::ptr; -use winapi::ctypes::c_long; -use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE}; -use winapi::shared::ntdef::HANDLE; -use winapi::um::consoleapi::SetConsoleCtrlHandler; -use winapi::um::handleapi::CloseHandle; -use winapi::um::synchapi::{ReleaseSemaphore, WaitForSingleObject}; -use winapi::um::winbase::{CreateSemaphoreA, INFINITE, WAIT_FAILED, WAIT_OBJECT_0}; +use windows_sys::Win32::Foundation::{CloseHandle, BOOL, HANDLE, WAIT_FAILED, WAIT_OBJECT_0}; +use windows_sys::Win32::System::Console::SetConsoleCtrlHandler; +use windows_sys::Win32::System::Threading::{ + CreateSemaphoreA, ReleaseSemaphore, WaitForSingleObject, INFINITE, +}; /// Platform specific error type pub type Error = io::Error; /// Platform specific signal type -pub type Signal = DWORD; +pub type Signal = u32; -const MAX_SEM_COUNT: c_long = 255; +const MAX_SEM_COUNT: i32 = 255; static mut SEMAPHORE: HANDLE = 0 as HANDLE; +const TRUE: BOOL = 1; +const FALSE: BOOL = 0; -unsafe extern "system" fn os_handler(_: DWORD) -> BOOL { +unsafe extern "system" fn os_handler(_: u32) -> BOOL { // Assuming this always succeeds. Can't really handle errors in any meaningful way. ReleaseSemaphore(SEMAPHORE, 1, ptr::null_mut()); TRUE @@ -41,9 +41,9 @@ /// Will return an error if a system error occurred. /// #[inline] -pub unsafe fn init_os_handler() -> Result<(), Error> { +pub unsafe fn init_os_handler(_overwrite: bool) -> Result<(), Error> { SEMAPHORE = CreateSemaphoreA(ptr::null_mut(), 0, MAX_SEM_COUNT, ptr::null()); - if SEMAPHORE.is_null() { + if SEMAPHORE == 0 { return Err(io::Error::last_os_error()); } diff -Nru rust-ctrlc-3.2.3/src/tests.rs rust-ctrlc-3.4.0/src/tests.rs --- rust-ctrlc-3.2.3/src/tests.rs 1973-11-29 21:33:09.000000000 +0000 +++ rust-ctrlc-3.4.0/src/tests.rs 1970-01-01 00:00:00.000000000 +0000 @@ -1,275 +0,0 @@ -// Copyright (c) 2017 CtrlC developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -#[cfg(unix)] -mod platform { - use std::io; - - pub unsafe fn setup() -> io::Result<()> { - Ok(()) - } - - pub unsafe fn cleanup() -> io::Result<()> { - Ok(()) - } - - pub unsafe fn raise_ctrl_c() { - nix::sys::signal::raise(nix::sys::signal::SIGINT).unwrap(); - } - - pub unsafe fn print(fmt: ::std::fmt::Arguments) { - use self::io::Write; - let stdout = ::std::io::stdout(); - stdout.lock().write_fmt(fmt).unwrap(); - } -} - -#[cfg(windows)] -mod platform { - use std::io; - use std::ptr; - - use winapi::shared::minwindef::DWORD; - use winapi::shared::ntdef::{CHAR, HANDLE}; - use winapi::um::consoleapi::{AllocConsole, GetConsoleMode}; - use winapi::um::fileapi::WriteFile; - use winapi::um::handleapi::INVALID_HANDLE_VALUE; - use winapi::um::processenv::{GetStdHandle, SetStdHandle}; - use winapi::um::winbase::{STD_ERROR_HANDLE, STD_OUTPUT_HANDLE}; - use winapi::um::wincon::{AttachConsole, FreeConsole, GenerateConsoleCtrlEvent}; - - /// Stores a piped stdout handle or a cache that gets - /// flushed when we reattached to the old console. - enum Output { - Pipe(HANDLE), - Cached(Vec), - } - - static mut OLD_OUT: *mut Output = 0 as *mut Output; - - impl io::Write for Output { - fn write(&mut self, buf: &[u8]) -> io::Result { - match *self { - Output::Pipe(handle) => unsafe { - use winapi::shared::ntdef::VOID; - - let mut n = 0u32; - if WriteFile( - handle, - buf.as_ptr() as *const VOID, - buf.len() as DWORD, - &mut n as *mut DWORD, - ptr::null_mut(), - ) == 0 - { - Err(io::Error::last_os_error()) - } else { - Ok(n as usize) - } - }, - Output::Cached(ref mut s) => s.write(buf), - } - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - } - - impl Output { - /// Stores current piped stdout or creates a new output cache that will - /// be written to stdout at a later time. - fn new() -> io::Result { - unsafe { - let stdout = GetStdHandle(STD_OUTPUT_HANDLE); - if stdout.is_null() || stdout == INVALID_HANDLE_VALUE { - return Err(io::Error::last_os_error()); - } - - let mut out = 0u32; - match GetConsoleMode(stdout, &mut out as *mut DWORD) { - 0 => Ok(Output::Pipe(stdout)), - _ => Ok(Output::Cached(Vec::new())), - } - } - } - - /// Set stdout/stderr and flush cache. - unsafe fn set_as_std(self) -> io::Result<()> { - let stdout = match self { - Output::Pipe(h) => h, - Output::Cached(_) => get_stdout()?, - }; - - if SetStdHandle(STD_OUTPUT_HANDLE, stdout) == 0 { - return Err(io::Error::last_os_error()); - } - - if SetStdHandle(STD_ERROR_HANDLE, stdout) == 0 { - return Err(io::Error::last_os_error()); - } - - match self { - Output::Pipe(_) => Ok(()), - Output::Cached(ref s) => { - // Write cached output - use self::io::Write; - let out = io::stdout(); - out.lock().write_all(&s[..])?; - Ok(()) - } - } - } - } - - unsafe fn get_stdout() -> io::Result { - use winapi::um::fileapi::{CreateFileA, OPEN_EXISTING}; - use winapi::um::handleapi::INVALID_HANDLE_VALUE; - use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE}; - - let stdout = CreateFileA( - "CONOUT$\0".as_ptr() as *const CHAR, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_WRITE, - ptr::null_mut(), - OPEN_EXISTING, - 0, - ptr::null_mut(), - ); - - if stdout.is_null() || stdout == INVALID_HANDLE_VALUE { - Err(io::Error::last_os_error()) - } else { - Ok(stdout) - } - } - - /// Detach from the current console and create a new one, - /// We do this because GenerateConsoleCtrlEvent() sends ctrl-c events - /// to all processes on the same console. We want events to be received - /// only by our process. - /// - /// This breaks rust's stdout pre 1.18.0. Rust used to - /// [cache the std handles](https://github.com/rust-lang/rust/pull/40516) - /// - pub unsafe fn setup() -> io::Result<()> { - let old_out = Output::new()?; - - if FreeConsole() == 0 { - return Err(io::Error::last_os_error()); - } - - if AllocConsole() == 0 { - return Err(io::Error::last_os_error()); - } - - // AllocConsole will not always set stdout/stderr to the to the console buffer - // of the new terminal. - - let stdout = get_stdout()?; - if SetStdHandle(STD_OUTPUT_HANDLE, stdout) == 0 { - return Err(io::Error::last_os_error()); - } - - if SetStdHandle(STD_ERROR_HANDLE, stdout) == 0 { - return Err(io::Error::last_os_error()); - } - - OLD_OUT = Box::into_raw(Box::new(old_out)); - - Ok(()) - } - - /// Reattach to the old console. - pub unsafe fn cleanup() -> io::Result<()> { - if FreeConsole() == 0 { - return Err(io::Error::last_os_error()); - } - - if AttachConsole(winapi::um::wincon::ATTACH_PARENT_PROCESS) == 0 { - return Err(io::Error::last_os_error()); - } - - Box::from_raw(OLD_OUT).set_as_std()?; - - Ok(()) - } - - /// This will signal the whole process group. - pub unsafe fn raise_ctrl_c() { - assert!(GenerateConsoleCtrlEvent(winapi::um::wincon::CTRL_C_EVENT, 0) != 0); - } - - /// Print to both consoles, this is not thread safe. - pub unsafe fn print(fmt: ::std::fmt::Arguments) { - use self::io::Write; - { - let stdout = io::stdout(); - stdout.lock().write_fmt(fmt).unwrap(); - } - { - assert!(!OLD_OUT.is_null()); - (*OLD_OUT).write_fmt(fmt).unwrap(); - } - } -} - -fn test_set_handler() { - let (tx, rx) = ::std::sync::mpsc::channel(); - ctrlc::set_handler(move || { - tx.send(true).unwrap(); - }) - .unwrap(); - - unsafe { - platform::raise_ctrl_c(); - } - - rx.recv_timeout(::std::time::Duration::from_secs(10)) - .unwrap(); - - match ctrlc::set_handler(|| {}) { - Err(ctrlc::Error::MultipleHandlers) => {} - ret => panic!("{:?}", ret), - } -} - -macro_rules! run_tests { - ( $($test_fn:ident),* ) => { - unsafe { - platform::print(format_args!("\n")); - $( - platform::print(format_args!("test tests::{} ... ", stringify!($test_fn))); - $test_fn(); - platform::print(format_args!("ok\n")); - )* - platform::print(format_args!("\n")); - } - } -} - -fn main() { - unsafe { - platform::setup().unwrap(); - } - - let default = std::panic::take_hook(); - std::panic::set_hook(Box::new(move |info| { - unsafe { - platform::cleanup().unwrap(); - } - (default)(info); - })); - - run_tests!(test_set_handler); - - unsafe { - platform::cleanup().unwrap(); - } -} diff -Nru rust-ctrlc-3.2.3/tests/main/harness.rs rust-ctrlc-3.4.0/tests/main/harness.rs --- rust-ctrlc-3.2.3/tests/main/harness.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-ctrlc-3.4.0/tests/main/harness.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,251 @@ +// Copyright (c) 2023 CtrlC developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +#[cfg(unix)] +pub mod platform { + use std::io; + + pub unsafe fn setup() -> io::Result<()> { + Ok(()) + } + + pub unsafe fn cleanup() -> io::Result<()> { + Ok(()) + } + + pub unsafe fn raise_ctrl_c() { + nix::sys::signal::raise(nix::sys::signal::SIGINT).unwrap(); + } + + pub unsafe fn print(fmt: ::std::fmt::Arguments) { + use self::io::Write; + let stdout = ::std::io::stdout(); + stdout.lock().write_fmt(fmt).unwrap(); + } +} + +#[cfg(windows)] +pub mod platform { + use std::io; + use std::ptr; + use windows_sys::Win32::Foundation::{ + GENERIC_READ, GENERIC_WRITE, HANDLE, INVALID_HANDLE_VALUE, + }; + use windows_sys::Win32::Storage::FileSystem::{ + CreateFileA, WriteFile, FILE_SHARE_WRITE, OPEN_EXISTING, + }; + use windows_sys::Win32::System::Console::{ + AllocConsole, AttachConsole, FreeConsole, GenerateConsoleCtrlEvent, GetConsoleMode, + GetStdHandle, SetStdHandle, ATTACH_PARENT_PROCESS, CTRL_C_EVENT, STD_ERROR_HANDLE, + STD_OUTPUT_HANDLE, + }; + + /// Stores a piped stdout handle or a cache that gets + /// flushed when we reattached to the old console. + enum Output { + Pipe(HANDLE), + Cached(Vec), + } + + static mut OLD_OUT: *mut Output = 0 as *mut Output; + + impl io::Write for Output { + fn write(&mut self, buf: &[u8]) -> io::Result { + match *self { + Output::Pipe(handle) => unsafe { + let mut n = 0u32; + if WriteFile( + handle, + buf.as_ptr(), + buf.len() as u32, + &mut n as *mut u32, + ptr::null_mut(), + ) == 0 + { + Err(io::Error::last_os_error()) + } else { + Ok(n as usize) + } + }, + Output::Cached(ref mut s) => s.write(buf), + } + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + } + + impl Output { + /// Stores current piped stdout or creates a new output cache that will + /// be written to stdout at a later time. + fn new() -> io::Result { + unsafe { + let stdout = GetStdHandle(STD_OUTPUT_HANDLE); + if stdout == 0 || stdout == INVALID_HANDLE_VALUE { + return Err(io::Error::last_os_error()); + } + + let mut out = 0u32; + match GetConsoleMode(stdout, &mut out as *mut u32) { + 0 => Ok(Output::Pipe(stdout)), + _ => Ok(Output::Cached(Vec::new())), + } + } + } + + /// Set stdout/stderr and flush cache. + unsafe fn set_as_std(self) -> io::Result<()> { + let stdout = match self { + Output::Pipe(h) => h, + Output::Cached(_) => get_stdout()?, + }; + + if SetStdHandle(STD_OUTPUT_HANDLE, stdout) == 0 { + return Err(io::Error::last_os_error()); + } + + if SetStdHandle(STD_ERROR_HANDLE, stdout) == 0 { + return Err(io::Error::last_os_error()); + } + + match self { + Output::Pipe(_) => Ok(()), + Output::Cached(ref s) => { + // Write cached output + use self::io::Write; + let out = io::stdout(); + out.lock().write_all(&s[..])?; + Ok(()) + } + } + } + } + + unsafe fn get_stdout() -> io::Result { + let stdout = CreateFileA( + "CONOUT$\0".as_ptr(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_EXISTING, + 0, + 0 as HANDLE, + ); + + if stdout == 0 || stdout == INVALID_HANDLE_VALUE { + Err(io::Error::last_os_error()) + } else { + Ok(stdout) + } + } + + /// Detach from the current console and create a new one, + /// We do this because GenerateConsoleCtrlEvent() sends ctrl-c events + /// to all processes on the same console. We want events to be received + /// only by our process. + /// + /// This breaks rust's stdout pre 1.18.0. Rust used to + /// [cache the std handles](https://github.com/rust-lang/rust/pull/40516) + /// + pub unsafe fn setup() -> io::Result<()> { + let old_out = Output::new()?; + + if FreeConsole() == 0 { + return Err(io::Error::last_os_error()); + } + + if AllocConsole() == 0 { + return Err(io::Error::last_os_error()); + } + + // AllocConsole will not always set stdout/stderr to the to the console buffer + // of the new terminal. + + let stdout = get_stdout()?; + if SetStdHandle(STD_OUTPUT_HANDLE, stdout) == 0 { + return Err(io::Error::last_os_error()); + } + + if SetStdHandle(STD_ERROR_HANDLE, stdout) == 0 { + return Err(io::Error::last_os_error()); + } + + OLD_OUT = Box::into_raw(Box::new(old_out)); + + Ok(()) + } + + /// Reattach to the old console. + pub unsafe fn cleanup() -> io::Result<()> { + if FreeConsole() == 0 { + return Err(io::Error::last_os_error()); + } + + if AttachConsole(ATTACH_PARENT_PROCESS) == 0 { + return Err(io::Error::last_os_error()); + } + + Box::from_raw(OLD_OUT).set_as_std()?; + + Ok(()) + } + + /// This will signal the whole process group. + pub unsafe fn raise_ctrl_c() { + assert!(GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) != 0); + } + + /// Print to both consoles, this is not thread safe. + pub unsafe fn print(fmt: ::std::fmt::Arguments) { + use self::io::Write; + { + let stdout = io::stdout(); + stdout.lock().write_fmt(fmt).unwrap(); + } + { + assert!(!OLD_OUT.is_null()); + (*OLD_OUT).write_fmt(fmt).unwrap(); + } + } +} + +macro_rules! run_tests { + ( $($test_fn:ident),* ) => { + unsafe { + $( + harness::platform::print(format_args!("test {} ... ", stringify!($test_fn))); + $test_fn(); + harness::platform::print(format_args!("ok\n")); + )* + } + } +} + +pub fn run_harness(f: fn()) { + unsafe { + platform::setup().unwrap(); + } + + let default = std::panic::take_hook(); + std::panic::set_hook(Box::new(move |info| { + unsafe { + platform::cleanup().unwrap(); + } + (default)(info); + })); + + println!(""); + f(); + println!(""); + + unsafe { + platform::cleanup().unwrap(); + } +} diff -Nru rust-ctrlc-3.2.3/tests/main/issue_97.rs rust-ctrlc-3.4.0/tests/main/issue_97.rs --- rust-ctrlc-3.2.3/tests/main/issue_97.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-ctrlc-3.4.0/tests/main/issue_97.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,32 @@ +// Copyright (c) 2023 CtrlC developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +#[macro_use] +mod harness; +use harness::{platform, run_harness}; + +mod test_signal_hook; +use test_signal_hook::run_signal_hook; + +fn expect_multiple_handlers() { + #[cfg(not(windows))] + match ctrlc::try_set_handler(|| {}) { + Err(ctrlc::Error::MultipleHandlers) => {} + _ => panic!("Expected Error::MultipleHandlers"), + } +} + +fn tests() { + run_tests!(run_signal_hook); + run_tests!(expect_multiple_handlers); +} + +fn main() { + run_harness(tests); +} diff -Nru rust-ctrlc-3.2.3/tests/main/mod.rs rust-ctrlc-3.4.0/tests/main/mod.rs --- rust-ctrlc-3.2.3/tests/main/mod.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-ctrlc-3.4.0/tests/main/mod.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,46 @@ +// Copyright (c) 2023 CtrlC developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +#[macro_use] +mod harness; +use harness::{platform, run_harness}; + +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; + +fn test_set_handler() { + let flag = Arc::new(AtomicBool::new(false)); + let flag_handler = Arc::clone(&flag); + ctrlc::set_handler(move || { + flag_handler.store(true, Ordering::SeqCst); + }) + .unwrap(); + + unsafe { + platform::raise_ctrl_c(); + } + + std::thread::sleep(std::time::Duration::from_millis(100)); + assert!(flag.load(Ordering::SeqCst)); + + match ctrlc::set_handler(|| {}) { + Err(ctrlc::Error::MultipleHandlers) => {} + ret => panic!("{:?}", ret), + } +} + +fn tests() { + run_tests!(test_set_handler); +} + +fn main() { + run_harness(tests); +} diff -Nru rust-ctrlc-3.2.3/tests/main/test_signal_hook.rs rust-ctrlc-3.4.0/tests/main/test_signal_hook.rs --- rust-ctrlc-3.2.3/tests/main/test_signal_hook.rs 1970-01-01 00:00:00.000000000 +0000 +++ rust-ctrlc-3.4.0/tests/main/test_signal_hook.rs 2006-07-24 01:21:28.000000000 +0000 @@ -0,0 +1,26 @@ +// Copyright (c) 2023 CtrlC developers +// Licensed under the Apache License, Version 2.0 +// or the MIT +// license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; + +pub fn run_signal_hook() { + let hook = Arc::new(AtomicBool::new(false)); + + signal_hook::flag::register(signal_hook::consts::SIGINT, Arc::clone(&hook)).unwrap(); + + unsafe { + super::platform::raise_ctrl_c(); + } + + std::thread::sleep(std::time::Duration::from_millis(100)); + assert!(hook.load(Ordering::SeqCst)); +}