diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:36 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:36 +0000 |
commit | e02c5b5930c2c9ba3e5423fe12e2ef0155017297 (patch) | |
tree | fd60ebbbb5299e16e5fca8c773ddb74f764760db /vendor/signal-hook | |
parent | Adding debian version 1.73.0+dfsg1-1. (diff) | |
download | rustc-e02c5b5930c2c9ba3e5423fe12e2ef0155017297.tar.xz rustc-e02c5b5930c2c9ba3e5423fe12e2ef0155017297.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/signal-hook')
27 files changed, 0 insertions, 4269 deletions
diff --git a/vendor/signal-hook/.cargo-checksum.json b/vendor/signal-hook/.cargo-checksum.json deleted file mode 100644 index 9c6dd5450..000000000 --- a/vendor/signal-hook/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"20a9b9bd056e5fbb980b7c5a7fc706dd32309743eeff23c5d4228ac10fca5b7b","Cargo.lock":"284dcdbc909099e591c59d059e66aa435d463c232f5fd0759b9732780d27fd8f","Cargo.toml":"41ccc6b0e364bc0da0a42496fa079037edad3f3bdb711a944f3332db89a9e18d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"503558bfefe66ca15e4e3f7955b3cb0ec87fd52f29bf24b336af7bd00e946d5c","README.md":"be97b822f26b642165c4fac3ed6a515f2c522f30c12a2011aa3b5cab1eb988d0","build.rs":"3a95a69d2921f1c28922a141a671e23a061f358b6d831350043003e13ef96463","ci-check.sh":"65f6e254cca1adf4579998fa393521cef8bc5bfbfb79b9fb430e1814a5a7c091","examples/print.rs":"ff4e0aeaf2533e7b48edec866cd6b65021a1e588e22d9a443a631d750daa36a0","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/flag.rs":"c240f03b5895a24803192a720ac3280c43d83867ca414e0622f53f90d287d07f","src/iterator/backend.rs":"98096e6fa7c3187c81acf8bf68b4aef013019a993dcdcde37b235bdfaf3c1561","src/iterator/exfiltrator/mod.rs":"c5476b32f00094e7556350c79bff7cec88e890750a42b613a5bf00e33234311f","src/iterator/exfiltrator/origin.rs":"ada8f6289c9b31d523f3cc9e02d533a3f348cfad6f5fc59ab929f851816ed156","src/iterator/exfiltrator/raw.rs":"22085d408ed660d6a2cb744f2c1bd321dbe261dfcc8858c41ad3ff9d367609c9","src/iterator/mod.rs":"d0c5e02df18ab578f98d4fa8b3c0d6c1f74a9c76033468216cb1704c946eb5f2","src/lib.rs":"968a13e57ba4c5a05f6a73aab83a6f4fae72d79a235129e09700946141c6c238","src/low_level/channel.rs":"7561da67226f0c668adc06d398d5a6f0f84a67b90092067e14359e9ee05cdac1","src/low_level/extract.c":"7583e69e6d0e57893dc6813ec6a519a83c86f9d1e4129812eacaca630dcf1c9d","src/low_level/mod.rs":"91b2a8995a7dcb71cf50bc5ead532e5ee706c77b7af99dbf6fc55c4a1516f03f","src/low_level/pipe.rs":"544d780577ba802af32abd7a075a3702f36b644d16baf3c2708ccec373b01c61","src/low_level/siginfo.rs":"3a416031a654add7b39a2a6c0328e6c60dbf33ca972a45ef11eaf198615a0aaf","src/low_level/signal_details.rs":"93d68af97fa45435e0236e96412eeea60ac2715eac0aa0648f27837537a722f1","tests/default.rs":"2e6e400990d31a5968f6909278e9cf20b75ba7f1a92b8485122ac790a2e94a44","tests/iterator.rs":"1533f9722c047a221a6e8903d179cace76c395fff54df010e42fbcaabeca7bc9","tests/shutdown.rs":"3ca8dbf94eead616bd47968f029a91c6bdffc9fb44be3f004d6e8fe2ac46db00"},"package":"732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"}
\ No newline at end of file diff --git a/vendor/signal-hook/CHANGELOG.md b/vendor/signal-hook/CHANGELOG.md deleted file mode 100644 index 7277e7631..000000000 --- a/vendor/signal-hook/CHANGELOG.md +++ /dev/null @@ -1,256 +0,0 @@ -# 0.3.15 -# signal-hook-registry-1.4.1 - -* AIX support (experimental/not guaranteed to work). - -# 0.3.14 - -* Added the SIGINFO signal (where available). - -# signal-hook-mio-0.2.3 - -* Support for mio 0.8 - -# signal-hook-async-std-0.2.2 -# signal-hook-tokio-0.3.1 - -* Fix support for SignalsInfo with non-default info extractors. - -# 0.3.13 - -* Add haiku support. - -# 0.3.12 - -* Fix accidentally broken windows build. - -# 0.3.11 - -* Provide fallback sigaddset, sigemptyset on certain androids, as they are - missing them. - -# 0.3.10 - -* Doc link fixes. - -# 0.3.9 - -* Deliver SIGCHLD even on stop/continue. - -# 0.3.8 - -* Fix docs.rs build. - -# 0.3.7 - -* Unmask a signal in default emulation if it is termination. - -# mio-0.2.2 - -* The same fix, but for the 0.6 support 😇. - -# mio-0.2.1 - -* Fix example: handle ErrorKind::Interrupted inside poll. It's very likely to - happen, when we are waiting for signals there. - -# 0.3.6 - -* Fix the labels on docs.rs :-|. - -# 0.3.5 - -* Doc: include the features & these little labels inside docs. - -# signal-hook-async-std-0.2.1 - -* Dependency updates ‒ no longer depends on the whole async-std, but only on - some smaller dependencies of it (`async-io`, `futures-lite`). This might make - it work even outside of async-std context. - -# signal-hook-tokio-0.3.0 - -* Support for tokio 1.0. - -# 0.3.4 - -* Fix feature dependencies (`iterator` depends on `channel`). - -# 0.3.3 - -* `low_level::emulate_default_handler` to emulate whatever default handler would - do. -* `low_level::signal_name` to look up human readable name. -* The `Origin`'s debug output now contains the human readable name of the - signal. - -# 0.3.2 - -* Allow extracting Origin from the raw `siginfo_t` structure by hand, without - needing an iterator. -* Folding the signal-hook-sys inline (but still compiling C code only - conditionally). -* `WithRawSiginfo` extractor (to get hands on the raw `siginfo_t`). -* Bugfix: Don't leak on WithOrigin destruction. - -# 0.3.1 - -* Use caret dependencies where appropriate (to allow upgrades on - signal-hook-registry). - -# async-std-0.2.0 - -* No longer depends on `futures`. - -# 0.3.0 - -* The `cleanup` module is gone, it was not a good API. Replaced by conditional - termination in `flag`. -* Some abstractions/patterns are moved to `low_level` submodule, as they are - considered building blocks, not for direct use (`register`, `pipe`, - `channel`). -* The signal constants are moved to a submodule (`consts`), together with few - more constants, to not clutter the root. -* The forever iterator no longer consumes. - -# registry-1.3.0 - -* The `unregister_signal` in is deprecated, without a replacement. - -# 0.2.2 - -* Extractor for the origin of a signal (PID, UID, what caused it). -* Fixing some doc links on re-exports. - -# 0.2.1 - -* Allow turning the iterator module off (the `iterator` feature, part of default - features). This would allow compiling the crate on 1.31.0. - -# 0.2.0 - -* Bump minimal rustc version to 1.36.0 (signal-hook-registry still builds with - 1.26.0). -* (Breaking) Support for exfiltrators ‒ ability to return more than just the - signal number from the iterator and streams. Nothing more is implemented yet, - but the place to put it is reserved in the API. -* (Breaking) `pipe::register_raw` now takes ownership and tries to use send - first, falls back to `O_NONBLOCK` and `write` on failure. -* (Breaking) All async support is pulled out into separate crates, to decouple - from the async runtime release cycles on the main `signal-hook` crate. -* Inner parts of the `Iterator` are now exposed in - `signal_hook::iterator::backend`, to support the async crates. - -# registry-1.2.2 - -* Drop dependency on arc-swap (only very small subset used and arc-swap would - like to drop that part anyway). - -# registry-1.2.1 - -* Abort instead of panicking if the OS gives us NULL as siginfo (which is - illegal). Panicking would be UB. - -# 0.1.16 - -* Fix possible blocking in signal handler registered by `Signals`. - -# 0.1.15 - -* Make `Signals` work in edge-triggered mode in mio too, by always draining - everything from the socket. Needed, because mio 0.7 doesn't have - level-triggered any more. - -# 0.1.14 - -* `mio-0_7-support` feature for use with mio 0.7.0+. -* Bump minimal rustc version to 1.31.0 (signal-hook-registry can still build - with 1.26.0). - -# 0.1.13 - -* Some doc clarifications. - -# 0.1.12 - -* `cleanup` module to register resetting signals to default. - -# registry-1.2.0 - -* `unregister_signal`, to remove all hooks of one signal. - -# 0.1.11 - -* Docs improvements. -* Fix registering pipes as well as sockets into the pipe module (#27). - -# registry-1.1.1 - -* Update deps. - -# registry-1.1.0 - -* Adding Windows support (thanks to @qnighy). - -# 0.1.10 - -* Fix busy loop in Iterator::forever when the mio-support feature is enabled - (#16). - -# registry-1.0.1 - -* Include the registry files in the crates.io tarball. - -# 0.1.9 -# registry-1.0.0 - -* Split into backend signal-hook-registry and the frontend. The backend is much - less likely to have breaking changes so it contains the things that can be in - the application just once. - -# 0.1.8 - -* The `Signals` iterator can now be closed (from another instance or thread), - which can be used to shut down the thread handling signals from the main - thread. - -# 0.1.7 - -* The `Signals` iterator allows adding signals after creation. -* Fixed a bug where `Signals` registrations could be unregirestered too soon if - the `Signals` was cloned previously. - -# 0.1.6 - -* The internally used ArcSwap thing doesn't block other ArcSwaps now (has - independent generation lock). - -# 0.1.5 - -* Re-exported signal constants, so users no longer need libc. - -# 0.1.4 - -* Compilation fix for android-aarch64 - -# 0.1.3 - -* Tokio support. -* Mio support. -* Dependency updates. - -# 0.1.2 - -* Dependency updates. - -# 0.1.1 - -* Get rid of `catch_unwind` inside the signal handler. -* Link to the nix crate. - -# 0.1.0 - -* Initial basic implementation. -* Flag helpers. -* Pipe helpers. -* High-level iterator helper. diff --git a/vendor/signal-hook/Cargo.lock b/vendor/signal-hook/Cargo.lock deleted file mode 100644 index d969becf3..000000000 --- a/vendor/signal-hook/Cargo.lock +++ /dev/null @@ -1,260 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -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" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" - -[[package]] -name = "lock_api" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" -dependencies = [ - "bitflags", -] - -[[package]] -name = "rustversion" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "serial_test" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19dbfb999a147cedbfe82f042eb9555f5b0fa4ef95ee4570b74349103d9c9f4" -dependencies = [ - "lazy_static", - "log", - "parking_lot", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9e2050b2be1d681f8f1c1a528bcfe4e00afa2d8995f713974f5333288659f2" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - -[[package]] -name = "signal-hook" -version = "0.3.15" -dependencies = [ - "cc", - "libc", - "serial_test", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "smallvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" - -[[package]] -name = "syn" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/vendor/signal-hook/Cargo.toml b/vendor/signal-hook/Cargo.toml deleted file mode 100644 index 45e3e13f6..000000000 --- a/vendor/signal-hook/Cargo.toml +++ /dev/null @@ -1,66 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2018" -name = "signal-hook" -version = "0.3.15" -authors = [ - "Michal 'vorner' Vaner <vorner@vorner.cz>", - "Thomas Himmelstoss <thimm@posteo.de>", -] -description = "Unix signal handling" -documentation = "https://docs.rs/signal-hook" -readme = "README.md" -keywords = [ - "signal", - "unix", - "daemon", -] -license = "Apache-2.0/MIT" -repository = "https://github.com/vorner/signal-hook" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", -] - -[dependencies.libc] -version = "^0.2" - -[dependencies.signal-hook-registry] -version = "^1.4" - -[dev-dependencies.serial_test] -version = "^0.7" - -[build-dependencies.cc] -version = "^1" -optional = true - -[features] -channel = [] -default = [ - "channel", - "iterator", -] -extended-siginfo = [ - "channel", - "iterator", - "extended-siginfo-raw", -] -extended-siginfo-raw = ["cc"] -iterator = ["channel"] - -[badges.maintenance] -status = "actively-developed" diff --git a/vendor/signal-hook/LICENSE-APACHE b/vendor/signal-hook/LICENSE-APACHE deleted file mode 100644 index 16fe87b06..000000000 --- a/vendor/signal-hook/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/signal-hook/LICENSE-MIT b/vendor/signal-hook/LICENSE-MIT deleted file mode 100644 index ebe0bc91e..000000000 --- a/vendor/signal-hook/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2017 tokio-jsonrpc developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/vendor/signal-hook/README.md b/vendor/signal-hook/README.md deleted file mode 100644 index 71a3d2701..000000000 --- a/vendor/signal-hook/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# Signal-hook - -[![Actions Status](https://github.com/vorner/signal-hook/workflows/test/badge.svg)](https://github.com/vorner/signal-hook/actions) -[![codecov](https://codecov.io/gh/vorner/signal-hook/branch/master/graph/badge.svg?token=3KA3R2D9fV)](https://codecov.io/gh/vorner/signal-hook) -[![docs](https://docs.rs/signal-hook/badge.svg)](https://docs.rs/signal-hook) - -Library for safe and correct Unix signal handling in Rust. - -Unix signals are inherently hard to handle correctly, for several reasons: - -* They are a global resource. If a library wants to set its own signal handlers, - it risks disturbing some other library. It is possible to chain the previous - signal handler, but then it is impossible to remove the old signal handlers - from the chains in any practical manner. -* They can be called from whatever thread, requiring synchronization. Also, as - they can interrupt a thread at any time, making most handling race-prone. -* According to the POSIX standard, the set of functions one may call inside a - signal handler is limited to very few of them. To highlight, mutexes (or other - locking mechanisms) and memory allocation and deallocation are *not* allowed. - -This library aims to solve some of the problems. It provides a global registry -of actions performed on arrival of signals. It is possible to register multiple -actions for the same signal and it is possible to remove the actions later on. -If there was a previous signal handler when the first action for a signal is -registered, it is chained (but the original one can't be removed). - -Besides the basic registration of an arbitrary action, several helper actions -are provided to cover the needs of the most common use cases, available from -safe Rust. - -For further details, see the [documentation](https://docs.rs/signal-hook). - -## Example - -(This likely does a lot more than you need in each individual application, it's -more of a show-case of what everything is possible, not of what you need to do -each time). - -```rust -use std::io::Error; -use std::sync::Arc; -use std::sync::atomic::{AtomicBool, Ordering}; - -fn main() -> Result<(), Error> { - let term = Arc::new(AtomicBool::new(false)); - signal_hook::flag::register(signal_hook::consts::SIGTERM, Arc::clone(&term))?; - while !term.load(Ordering::Relaxed) { - // Do some time-limited stuff here - // (if this could block forever, then there's no guarantee the signal will have any - // effect). - } - Ok(()) -} -``` - -## License - -Licensed under either of - - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally -submitted for inclusion in the work by you, as defined in the Apache-2.0 -license, shall be dual licensed as above, without any additional terms -or conditions. diff --git a/vendor/signal-hook/build.rs b/vendor/signal-hook/build.rs deleted file mode 100644 index 82545f1ec..000000000 --- a/vendor/signal-hook/build.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[cfg(feature = "extended-siginfo-raw")] -fn main() { - cc::Build::new() - .file("src/low_level/extract.c") - .compile("extract"); -} - -#[cfg(not(feature = "extended-siginfo-raw"))] -fn main() {} diff --git a/vendor/signal-hook/ci-check.sh b/vendor/signal-hook/ci-check.sh deleted file mode 100755 index 05879b651..000000000 --- a/vendor/signal-hook/ci-check.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -# We try to support some older versions of rustc. However, the support is -# tiered a bit. Our dev-dependencies do *not* guarantee that old minimal -# version. So we don't do tests on the older ones. Also, the -# signal-hook-registry supports older rustc than we signal-hook. - -set -ex - -rm -f Cargo.lock -cargo build --all --exclude signal-hook-async-std --exclude signal-hook-tokio - -if [ "$RUST_VERSION" = 1.36.0 ] ; then - exit -fi - -if [ "$OS" = "windows-latest" ] || [ "$RUST_VERSION" = 1.40.0 ]; then - # The async support crates rely on the iterator module - # which isn't available for windows. So exclude them - # from the build. - - # Also, some dependencies of the runtimes don't like 1.40. - EXCLUDE_FROM_BUILD="--exclude signal-hook-mio --exclude signal-hook-tokio --exclude signal-hook-async-std" -else - EXCLUDE_FROM_BUILD="" -fi - -export RUSTFLAGS="-D warnings" - -cargo test --all --all-features $EXCLUDE_FROM_BUILD -cargo test --all $EXCLUDE_FROM_BUILD diff --git a/vendor/signal-hook/examples/print.rs b/vendor/signal-hook/examples/print.rs deleted file mode 100644 index 4007f9171..000000000 --- a/vendor/signal-hook/examples/print.rs +++ /dev/null @@ -1,27 +0,0 @@ -use libc::c_int; -use signal_hook::consts::signal::*; -use signal_hook::low_level; - -use std::io::Error; - -#[cfg(feature = "extended-siginfo")] -type Signals = - signal_hook::iterator::SignalsInfo<signal_hook::iterator::exfiltrator::origin::WithOrigin>; - -#[cfg(not(feature = "extended-siginfo"))] -use signal_hook::iterator::Signals; - -fn main() -> Result<(), Error> { - const SIGNALS: &[c_int] = &[ - SIGTERM, SIGQUIT, SIGINT, SIGTSTP, SIGWINCH, SIGHUP, SIGCHLD, SIGCONT, - ]; - let mut sigs = Signals::new(SIGNALS)?; - for signal in &mut sigs { - eprintln!("Received signal {:?}", signal); - #[cfg(feature = "extended-siginfo")] - let signal = signal.signal; - // After printing it, do whatever the signal was supposed to do in the first place - low_level::emulate_default_handler(signal)?; - } - Ok(()) -} diff --git a/vendor/signal-hook/rustfmt.toml b/vendor/signal-hook/rustfmt.toml deleted file mode 100644 index e69de29bb..000000000 --- a/vendor/signal-hook/rustfmt.toml +++ /dev/null diff --git a/vendor/signal-hook/src/flag.rs b/vendor/signal-hook/src/flag.rs deleted file mode 100644 index 8573fcd7f..000000000 --- a/vendor/signal-hook/src/flag.rs +++ /dev/null @@ -1,283 +0,0 @@ -//! Module for actions setting flags. -//! -//! This contains helper functions to set flags whenever a signal happens. The flags are atomic -//! bools or numbers and the library manipulates them with the `SeqCst` ordering, in case someone -//! cares about relative order to some *other* atomic variables. If you don't care about the -//! relative order, you are free to use `Ordering::Relaxed` when reading and resetting the flags. -//! -//! # When to use -//! -//! The flags in this module allow for polling if a signal arrived since the previous poll. The do -//! not allow blocking until something arrives. -//! -//! Therefore, the natural way to use them is in applications that have some kind of iterative work -//! with both some upper and lower time limit on one iteration. If one iteration could block for -//! arbitrary time, the handling of the signal would be postponed for a long time. If the iteration -//! didn't block at all, the checking for the signal would turn into a busy-loop. -//! -//! If what you need is blocking until a signal comes, you might find better tools in the -//! [`pipe`][crate::low_level::pipe] and [`iterator`][crate::iterator] modules. -//! -//! # Examples -//! -//! Doing something until terminated. This also knows by which signal it was terminated. In case -//! multiple termination signals arrive before it is handled, it recognizes the last one. -//! -//! ```rust -//! use std::io::Error; -//! use std::sync::Arc; -//! use std::sync::atomic::{AtomicUsize, Ordering}; -//! -//! use signal_hook::consts::signal::*; -//! use signal_hook::flag as signal_flag; -//! -//! fn main() -> Result<(), Error> { -//! let term = Arc::new(AtomicUsize::new(0)); -//! const SIGTERM_U: usize = SIGTERM as usize; -//! const SIGINT_U: usize = SIGINT as usize; -//! # #[cfg(not(windows))] -//! const SIGQUIT_U: usize = SIGQUIT as usize; -//! signal_flag::register_usize(SIGTERM, Arc::clone(&term), SIGTERM_U)?; -//! signal_flag::register_usize(SIGINT, Arc::clone(&term), SIGINT_U)?; -//! # #[cfg(not(windows))] -//! signal_flag::register_usize(SIGQUIT, Arc::clone(&term), SIGQUIT_U)?; -//! -//! # // Hack to terminate the example when run as a doc-test. -//! # term.store(SIGTERM_U, Ordering::Relaxed); -//! loop { -//! match term.load(Ordering::Relaxed) { -//! 0 => { -//! // Do some useful stuff here -//! } -//! SIGTERM_U => { -//! eprintln!("Terminating on the TERM signal"); -//! break; -//! } -//! SIGINT_U => { -//! eprintln!("Terminating on the INT signal"); -//! break; -//! } -//! # #[cfg(not(windows))] -//! SIGQUIT_U => { -//! eprintln!("Terminating on the QUIT signal"); -//! break; -//! } -//! _ => unreachable!(), -//! } -//! } -//! -//! Ok(()) -//! } -//! ``` -//! -//! Sending a signal to self and seeing it arrived (not of a practical usage on itself): -//! -//! ```rust -//! use std::io::Error; -//! use std::sync::Arc; -//! use std::sync::atomic::{AtomicBool, Ordering}; -//! use std::thread; -//! use std::time::Duration; -//! -//! use signal_hook::consts::signal::*; -//! use signal_hook::low_level::raise; -//! -//! fn main() -> Result<(), Error> { -//! let got = Arc::new(AtomicBool::new(false)); -//! # #[cfg(not(windows))] -//! signal_hook::flag::register(SIGUSR1, Arc::clone(&got))?; -//! # #[cfg(windows)] -//! # signal_hook::flag::register(SIGTERM, Arc::clone(&got))?; -//! # #[cfg(not(windows))] -//! raise(SIGUSR1).unwrap(); -//! # #[cfg(windows)] -//! # raise(SIGTERM).unwrap(); -//! // A sleep here, because it could run the signal handler in another thread and we may not -//! // see the flag right away. This is still a hack and not guaranteed to work, it is just an -//! // example! -//! thread::sleep(Duration::from_secs(1)); -//! assert!(got.load(Ordering::Relaxed)); -//! Ok(()) -//! } -//! ``` -//! -//! Reloading a configuration on `SIGHUP` (which is a common behaviour of many UNIX daemons, -//! together with reopening the log file). -//! -//! ```rust -//! use std::io::Error; -//! use std::sync::Arc; -//! use std::sync::atomic::{AtomicBool, Ordering}; -//! -//! use signal_hook::consts::signal::*; -//! use signal_hook::flag as signal_flag; -//! -//! fn main() -> Result<(), Error> { -//! // We start with true, to load the configuration in the very first iteration too. -//! let reload = Arc::new(AtomicBool::new(true)); -//! let term = Arc::new(AtomicBool::new(false)); -//! # #[cfg(not(windows))] -//! signal_flag::register(SIGHUP, Arc::clone(&reload))?; -//! signal_flag::register(SIGINT, Arc::clone(&term))?; -//! signal_flag::register(SIGTERM, Arc::clone(&term))?; -//! # #[cfg(not(windows))] -//! signal_flag::register(SIGQUIT, Arc::clone(&term))?; -//! while !term.load(Ordering::Relaxed) { -//! // Using swap here, not load, to reset it back to false once it is reloaded. -//! if reload.swap(false, Ordering::Relaxed) { -//! // Reload the config here -//! # -//! # // Hiden hack to make the example terminate when run as doc-test. Not part of the -//! # // real code. -//! # term.store(true, Ordering::Relaxed); -//! } -//! // Serve one request -//! } -//! Ok(()) -//! } -//! ``` - -use std::io::Error; -use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use std::sync::Arc; - -use libc::{c_int, EINVAL}; - -use crate::{low_level, SigId}; - -/// Registers an action to set the flag to `true` whenever the given signal arrives. -/// -/// # Panics -/// -/// If the signal is one of the forbidden. -pub fn register(signal: c_int, flag: Arc<AtomicBool>) -> Result<SigId, Error> { - // We use SeqCst for two reasons: - // * Signals should not come very often, so the performance does not really matter. - // * We promise the order of actions, but setting different atomics with Relaxed or similar - // would not guarantee the effective order. - unsafe { low_level::register(signal, move || flag.store(true, Ordering::SeqCst)) } -} - -/// Registers an action to set the flag to the given value whenever the signal arrives. -pub fn register_usize(signal: c_int, flag: Arc<AtomicUsize>, value: usize) -> Result<SigId, Error> { - unsafe { low_level::register(signal, move || flag.store(value, Ordering::SeqCst)) } -} - -/// Terminate the application on a signal if the given condition is true. -/// -/// This can be used for different use cases. One of them (with the condition being always true) is -/// just unconditionally terminate on the given signal. -/// -/// Another is being able to turn on and off the behaviour by the shared flag. -/// -/// The last one is handling double CTRL+C ‒ if the user presses CTRL+C, we would like to start a -/// graceful shutdown. But if anything ever gets stuck in the shutdown, second CTRL+C (or other -/// such termination signal) should terminate the application without further delay. -/// -/// To do that, one can combine this with [`register`]. On the first run, the flag is `false` and -/// this doesn't terminate. But then the flag is set to true during the first run and „arms“ the -/// shutdown on the second run. Note that it matters in which order the actions are registered (the -/// shutdown must go first). And yes, this also allows asking the user „Do you want to terminate“ -/// and disarming the abrupt shutdown if the user answers „No“. -/// -/// # Panics -/// -/// If the signal is one of the forbidden. -pub fn register_conditional_shutdown( - signal: c_int, - status: c_int, - condition: Arc<AtomicBool>, -) -> Result<SigId, Error> { - let action = move || { - if condition.load(Ordering::SeqCst) { - low_level::exit(status); - } - }; - unsafe { low_level::register(signal, action) } -} - -/// Conditionally runs an emulation of the default action on the given signal. -/// -/// If the provided condition is true at the time of invoking the signal handler, the equivalent of -/// the default action of the given signal is run. It is a bit similar to -/// [`register_conditional_shutdown`], except that it doesn't terminate for non-termination -/// signals, it runs their default handler. -/// -/// # Panics -/// -/// If the signal is one of the forbidden -/// -/// # Errors -/// -/// Similarly to the [`emulate_default_handler`][low_level::emulate_default_handler] function, this -/// one looks the signal up in a table. If it is unknown, an error is returned. -/// -/// Additionally to that, any errors that can be caused by a registration of a handler can happen -/// too. -pub fn register_conditional_default( - signal: c_int, - condition: Arc<AtomicBool>, -) -> Result<SigId, Error> { - // Verify we know about this particular signal. - low_level::signal_name(signal).ok_or_else(|| Error::from_raw_os_error(EINVAL))?; - let action = move || { - if condition.load(Ordering::SeqCst) { - let _ = low_level::emulate_default_handler(signal); - } - }; - unsafe { low_level::register(signal, action) } -} - -#[cfg(test)] -mod tests { - use std::sync::atomic; - use std::time::{Duration, Instant}; - - use super::*; - use crate::consts::signal::*; - - fn self_signal() { - #[cfg(not(windows))] - const SIG: c_int = SIGUSR1; - #[cfg(windows)] - const SIG: c_int = SIGTERM; - crate::low_level::raise(SIG).unwrap(); - } - - fn wait_flag(flag: &AtomicBool) -> bool { - let start = Instant::now(); - while !flag.load(Ordering::Relaxed) { - // Replaced by hint::spin_loop, but we want to support older compiler - #[allow(deprecated)] - atomic::spin_loop_hint(); - if Instant::now() - start > Duration::from_secs(1) { - // We reached a timeout and nothing happened yet. - // In theory, using timeouts for thread-synchronization tests is wrong, but a - // second should be enough in practice. - return false; - } - } - true - } - - #[test] - fn register_unregister() { - // When we register the action, it is active. - let flag = Arc::new(AtomicBool::new(false)); - #[cfg(not(windows))] - let signal = register(SIGUSR1, Arc::clone(&flag)).unwrap(); - #[cfg(windows)] - let signal = register(crate::SIGTERM, Arc::clone(&flag)).unwrap(); - self_signal(); - assert!(wait_flag(&flag)); - // But stops working after it is unregistered. - assert!(crate::low_level::unregister(signal)); - flag.store(false, Ordering::Relaxed); - self_signal(); - assert!(!wait_flag(&flag)); - // And the unregistration actually dropped its copy of the Arc - assert_eq!(1, Arc::strong_count(&flag)); - } - - // The shutdown is tested in tests/shutdown.rs -} diff --git a/vendor/signal-hook/src/iterator/backend.rs b/vendor/signal-hook/src/iterator/backend.rs deleted file mode 100644 index 2ed4bf93a..000000000 --- a/vendor/signal-hook/src/iterator/backend.rs +++ /dev/null @@ -1,494 +0,0 @@ -//! A backend module for implementing the iterator like -//! [`iterator`][crate::iterator] module and the asynchronous -//! adapter crates. -//! -//! This module contains generic types which abstract over the concrete -//! IO type for the self-pipe. The motivation for having this abstraction -//! are the adapter crates for different asynchronous runtimes. The runtimes -//! provide their own wrappers for [`std::os::unix::net::UnixStream`] -//! which should be used as the internal self pipe. But large parts of the -//! remaining functionality doesn't depend directly onto the IO type and can -//! be reused. -//! -//! See also the [`SignalDelivery::with_pipe`] method for more information -//! about requirements the IO types have to fulfill. -//! -//! As a regular user you shouldn't need to use the types in this module. -//! Use the [`Signals`][crate::iterator::Signals] struct or one of the types -//! contained in the adapter libraries instead. - -use std::borrow::{Borrow, BorrowMut}; -use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::io::Error; -use std::mem::MaybeUninit; -use std::os::unix::io::AsRawFd; -use std::ptr; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex}; - -use libc::{self, c_int}; - -use super::exfiltrator::Exfiltrator; -use crate::low_level::pipe::{self, WakeMethod}; -use crate::SigId; - -/// Maximal signal number we support. -const MAX_SIGNUM: usize = 128; - -trait SelfPipeWrite: Debug + Send + Sync { - fn wake_readers(&self); -} - -impl<W: AsRawFd + Debug + Send + Sync> SelfPipeWrite for W { - fn wake_readers(&self) { - pipe::wake(self.as_raw_fd(), WakeMethod::Send); - } -} - -#[derive(Debug)] -struct DeliveryState { - closed: AtomicBool, - registered_signal_ids: Mutex<Vec<Option<SigId>>>, -} - -impl DeliveryState { - fn new() -> Self { - let ids = (0..MAX_SIGNUM).map(|_| None).collect(); - Self { - closed: AtomicBool::new(false), - registered_signal_ids: Mutex::new(ids), - } - } -} - -impl Drop for DeliveryState { - fn drop(&mut self) { - let lock = self.registered_signal_ids.lock().unwrap(); - for id in lock.iter().filter_map(|s| *s) { - crate::low_level::unregister(id); - } - } -} - -struct PendingSignals<E: Exfiltrator> { - exfiltrator: E, - slots: [E::Storage; MAX_SIGNUM], -} - -impl<E: Exfiltrator> PendingSignals<E> { - fn new(exfiltrator: E) -> Self { - // Unfortunately, Default is not implemented for long arrays :-( - // - // Note that if the default impl panics, the already existing instances are leaked. - let mut slots = MaybeUninit::<[E::Storage; MAX_SIGNUM]>::uninit(); - for i in 0..MAX_SIGNUM { - unsafe { - let slot: *mut E::Storage = slots.as_mut_ptr() as *mut _; - let slot = slot.add(i); - ptr::write(slot, E::Storage::default()); - } - } - - Self { - exfiltrator, - slots: unsafe { slots.assume_init() }, - } - } -} - -/// An internal trait to hide adding new signals into a Handle behind a dynamic dispatch. -trait AddSignal: Debug + Send + Sync { - fn add_signal( - self: Arc<Self>, - write: Arc<dyn SelfPipeWrite>, - signal: c_int, - ) -> Result<SigId, Error>; -} - -// Implemented manually because 1.36.0 doesn't yet support Debug for [X; BIG_NUMBER]. -impl<E: Exfiltrator> Debug for PendingSignals<E> { - fn fmt(&self, fmt: &mut Formatter) -> FmtResult { - fmt.debug_struct("PendingSignals") - .field("exfiltrator", &self.exfiltrator) - // While the array does not, the slice does implement Debug - .field("slots", &&self.slots[..]) - .finish() - } -} - -impl<E: Exfiltrator> AddSignal for PendingSignals<E> { - fn add_signal( - self: Arc<Self>, - write: Arc<dyn SelfPipeWrite>, - signal: c_int, - ) -> Result<SigId, Error> { - assert!(signal >= 0); - assert!( - (signal as usize) < MAX_SIGNUM, - "Signal number {} too large. If your OS really supports such signal, file a bug", - signal, - ); - assert!( - self.exfiltrator.supports_signal(signal), - "Signal {} not supported by exfiltrator {:?}", - signal, - self.exfiltrator, - ); - self.exfiltrator.init(&self.slots[signal as usize], signal); - - let action = move |act: &_| { - let slot = &self.slots[signal as usize]; - let ex = &self.exfiltrator; - ex.store(slot, signal, act); - write.wake_readers(); - }; - let id = unsafe { signal_hook_registry::register_sigaction(signal, action) }?; - Ok(id) - } -} - -/// A struct to control an instance of an associated type -/// (like for example [`Signals`][super::Signals]). -/// -/// It allows to register more signal handlers and to shutdown the signal -/// delivery. You can [`clone`][Handle::clone] this type which isn't a -/// very expensive operation. The cloned instances can be shared between -/// multiple threads. -#[derive(Debug, Clone)] -pub struct Handle { - pending: Arc<dyn AddSignal>, - write: Arc<dyn SelfPipeWrite>, - delivery_state: Arc<DeliveryState>, -} - -impl Handle { - fn new<W>(write: W, pending: Arc<dyn AddSignal>) -> Self - where - W: 'static + SelfPipeWrite, - { - Self { - pending, - write: Arc::new(write), - delivery_state: Arc::new(DeliveryState::new()), - } - } - - /// Registers another signal to the set watched by the associated instance. - /// - /// # Notes - /// - /// * This is safe to call concurrently from whatever thread. - /// * This is *not* safe to call from within a signal handler. - /// * If the signal number was already registered previously, this is a no-op. - /// * If this errors, the original set of signals is left intact. - /// - /// # Panics - /// - /// * If the given signal is [forbidden][crate::FORBIDDEN]. - /// * If the signal number is negative or larger than internal limit. The limit should be - /// larger than any supported signal the OS supports. - /// * If the relevant [`Exfiltrator`] does not support this particular signal. The default - /// [`SignalOnly`] one supports all signals. - pub fn add_signal(&self, signal: c_int) -> Result<(), Error> { - let mut lock = self.delivery_state.registered_signal_ids.lock().unwrap(); - // Already registered, ignoring - if lock[signal as usize].is_some() { - return Ok(()); - } - - let id = Arc::clone(&self.pending).add_signal(Arc::clone(&self.write), signal)?; - - lock[signal as usize] = Some(id); - - Ok(()) - } - - /// Closes the associated instance. - /// - /// This is meant to signalize termination of the signal delivery process. - /// After calling close: - /// - /// * [`is_closed`][Handle::is_closed] will return true. - /// * All currently blocking operations of associated instances - /// are interrupted and terminate. - /// * Any further operations will not block. - /// * Further signals may or may not be returned from the iterators. However, if any are - /// returned, these are real signals that happened. - /// - /// The goal is to be able to shut down any background thread that handles only the signals. - pub fn close(&self) { - self.delivery_state.closed.store(true, Ordering::SeqCst); - self.write.wake_readers(); - } - - /// Is it closed? - /// - /// See [`close`][Handle::close]. - pub fn is_closed(&self) -> bool { - self.delivery_state.closed.load(Ordering::SeqCst) - } -} - -/// A struct for delivering received signals to the main program flow. -/// The self-pipe IO type is generic. See the -/// [`with_pipe`][SignalDelivery::with_pipe] method for requirements -/// for the IO type. -#[derive(Debug)] -pub struct SignalDelivery<R, E: Exfiltrator> { - read: R, - handle: Handle, - pending: Arc<PendingSignals<E>>, -} - -impl<R, E: Exfiltrator> SignalDelivery<R, E> -where - R: 'static + AsRawFd + Send + Sync, -{ - /// Creates the `SignalDelivery` structure. - /// - /// The read and write arguments must be the ends of a suitable pipe type. These are used - /// for communication between the signal handler and main program flow. - /// - /// Registers all the signals listed. The same restrictions (panics, errors) apply as with - /// [`add_signal`][Handle::add_signal]. - /// - /// # Requirements for the pipe type - /// - /// * Must support [`send`](https://man7.org/linux/man-pages/man2/send.2.html) for - /// asynchronously writing bytes to the write end - /// * Must support [`recv`](https://man7.org/linux/man-pages/man2/recv.2.html) for - /// reading bytes from the read end - /// - /// So UnixStream is a good choice for this. - pub fn with_pipe<I, S, W>(read: R, write: W, exfiltrator: E, signals: I) -> Result<Self, Error> - where - I: IntoIterator<Item = S>, - S: Borrow<c_int>, - W: 'static + AsRawFd + Debug + Send + Sync, - { - let pending = Arc::new(PendingSignals::new(exfiltrator)); - let pending_add_signal = Arc::clone(&pending); - let handle = Handle::new(write, pending_add_signal); - let me = Self { - read, - handle, - pending, - }; - for sig in signals { - me.handle.add_signal(*sig.borrow())?; - } - Ok(me) - } - - /// Get a reference to the read end of the self pipe - /// - /// You may use this method to register the underlying file descriptor - /// with an eventing system (e. g. epoll) to get notified if there are - /// bytes in the pipe. If the event system reports the file descriptor - /// ready for reading you can then call [`pending`][SignalDelivery::pending] - /// to get the arrived signals. - pub fn get_read(&self) -> &R { - &self.read - } - - /// Get a mutable reference to the read end of the self pipe - /// - /// See the [`get_read`][SignalDelivery::get_read] method for some additional - /// information. - pub fn get_read_mut(&mut self) -> &mut R { - &mut self.read - } - - /// Drains all data from the internal self-pipe. This method will never block. - fn flush(&mut self) { - const SIZE: usize = 1024; - let mut buff = [0u8; SIZE]; - - unsafe { - // Draining the data in the self pipe. We ignore all errors on purpose. This - // should not be something like closed file descriptor. It could EAGAIN, but - // that's OK in case we say MSG_DONTWAIT. If it's EINTR, then it's OK too, - // it'll only create a spurious wakeup. - #[cfg(target_os = "aix")] - let nowait_flag = libc::MSG_NONBLOCK; - #[cfg(not(target_os = "aix"))] - let nowait_flag = libc::MSG_DONTWAIT; - while libc::recv( - self.read.as_raw_fd(), - buff.as_mut_ptr() as *mut libc::c_void, - SIZE, - nowait_flag, - ) > 0 - {} - } - } - - /// Returns an iterator of already received signals. - /// - /// This returns an iterator over all the signal numbers of the signals received since last - /// time they were read (out of the set registered by this `SignalDelivery` instance). Note - /// that they are returned in arbitrary order and a signal number is returned only once even - /// if it was received multiple times. - /// - /// This method returns immediately (does not block) and may produce an empty iterator if - /// there are no signals ready. - pub fn pending(&mut self) -> Pending<E> { - self.flush(); - Pending::new(Arc::clone(&self.pending)) - } - - /// Checks the reading end of the self pipe for available signals. - /// - /// If there are no signals available or this instance was already closed it returns - /// [`Option::None`]. If there are some signals it returns a [`Pending`] - /// instance wrapped inside a [`Option::Some`]. However, due to implementation details, - /// this still can produce an empty iterator. - /// - /// This method doesn't check the reading end by itself but uses the passed in callback. - /// This method blocks if and only if the callback blocks trying to read some bytes. - pub fn poll_pending<F>(&mut self, has_signals: &mut F) -> Result<Option<Pending<E>>, Error> - where - F: FnMut(&mut R) -> Result<bool, Error>, - { - if self.handle.is_closed() { - return Ok(None); - } - - match has_signals(self.get_read_mut()) { - Ok(false) => Ok(None), - Ok(true) => Ok(Some(self.pending())), - Err(err) => Err(err), - } - } - - /// Get a [`Handle`] for this `SignalDelivery` instance. - /// - /// This can be used to add further signals or close the whole - /// signal delivery mechanism. - pub fn handle(&self) -> Handle { - self.handle.clone() - } -} - -/// The iterator of one batch of signals. -/// -/// This is returned by the [`pending`][SignalDelivery::pending] method. -#[derive(Debug)] -pub struct Pending<E: Exfiltrator> { - pending: Arc<PendingSignals<E>>, - position: usize, -} - -impl<E: Exfiltrator> Pending<E> { - fn new(pending: Arc<PendingSignals<E>>) -> Self { - Self { - pending, - position: 0, - } - } -} - -impl<E: Exfiltrator> Iterator for Pending<E> { - type Item = E::Output; - - fn next(&mut self) -> Option<E::Output> { - while self.position < self.pending.slots.len() { - let sig = self.position; - let slot = &self.pending.slots[sig]; - let result = self.pending.exfiltrator.load(slot, sig as c_int); - if result.is_some() { - return result; - } else { - self.position += 1; - } - } - - None - } -} - -/// Possible results of the [`poll_signal`][SignalIterator::poll_signal] function. -pub enum PollResult<O> { - /// A signal arrived - Signal(O), - /// There are no signals yet but there may arrive some in the future - Pending, - /// The iterator was closed. There won't be any signals reported from now on. - Closed, - /// An error happened during polling for arrived signals. - Err(Error), -} - -/// An infinite iterator of received signals. -pub struct SignalIterator<SD, E: Exfiltrator> { - signals: SD, - iter: Pending<E>, -} - -impl<SD, E: Exfiltrator> SignalIterator<SD, E> { - /// Create a new infinite iterator for signals registered with the passed - /// in [`SignalDelivery`] instance. - pub fn new<R>(mut signals: SD) -> Self - where - SD: BorrowMut<SignalDelivery<R, E>>, - R: 'static + AsRawFd + Send + Sync, - { - let iter = signals.borrow_mut().pending(); - Self { signals, iter } - } - - /// Return a signal if there is one or tell the caller that there is none at the moment. - /// - /// You have to pass in a callback which checks the underlying reading end of the pipe if - /// there may be any pending signals. This callback may or may not block. If the callback - /// returns [`true`] this method will try to fetch the next signal and return it as a - /// [`PollResult::Signal`]. If the callback returns [`false`] the method will return - /// [`PollResult::Pending`] and assume it will be called again at a later point in time. - /// The callback may be called any number of times by this function. - /// - /// If the iterator was closed by the [`close`][Handle::close] method of the associtated - /// [`Handle`] this method will return [`PollResult::Closed`]. - pub fn poll_signal<R, F>(&mut self, has_signals: &mut F) -> PollResult<E::Output> - where - SD: BorrowMut<SignalDelivery<R, E>>, - R: 'static + AsRawFd + Send + Sync, - F: FnMut(&mut R) -> Result<bool, Error>, - { - // The loop is necessary because it is possible that a signal was already consumed - // by a previous pending iterator due to the asynchronous nature of signals and - // always moving to the end of the iterator before calling has_more. - while !self.signals.borrow_mut().handle.is_closed() { - if let Some(result) = self.iter.next() { - return PollResult::Signal(result); - } - - match self.signals.borrow_mut().poll_pending(has_signals) { - Ok(Some(pending)) => self.iter = pending, - Ok(None) => return PollResult::Pending, - Err(err) => return PollResult::Err(err), - } - } - - PollResult::Closed - } - - /// Get a shareable [`Handle`] for this instance. - /// - /// This can be used to add further signals or terminate the whole - /// signal iteration using the [`close`][Handle::close] method. - pub fn handle<R>(&self) -> Handle - where - SD: Borrow<SignalDelivery<R, E>>, - R: 'static + AsRawFd + Send + Sync, - { - self.signals.borrow().handle() - } -} - -/// A signal iterator which consumes a [`SignalDelivery`] instance and takes -/// ownership of it. -pub type OwningSignalIterator<R, E> = SignalIterator<SignalDelivery<R, E>, E>; - -/// A signal iterator which takes a mutable reference to a [`SignalDelivery`] -/// instance. -pub type RefSignalIterator<'a, R, E> = SignalIterator<&'a mut SignalDelivery<R, E>, E>; diff --git a/vendor/signal-hook/src/iterator/exfiltrator/mod.rs b/vendor/signal-hook/src/iterator/exfiltrator/mod.rs deleted file mode 100644 index 0b7cd0e34..000000000 --- a/vendor/signal-hook/src/iterator/exfiltrator/mod.rs +++ /dev/null @@ -1,152 +0,0 @@ -//! An abstraction over exfiltrating information out of signal handlers. -//! -//! The [`Exfiltrator`] trait provides a way to abstract the information extracted from a signal -//! handler and the way it is extracted out of it. -//! -//! The implementations can be used to parametrize the -//! [`SignalsInfo`][crate::iterator::SignalsInfo] to specify what results are returned. -//! -//! # Sealed -//! -//! Currently, the trait is sealed and all methods hidden. This is likely temporary, until some -//! experience with them is gained. - -#[cfg(feature = "extended-siginfo")] -#[cfg_attr(docsrs, doc(cfg(feature = "extended-siginfo")))] -pub mod origin; -pub mod raw; - -#[cfg(feature = "extended-siginfo")] -pub use origin::WithOrigin; -pub use raw::WithRawSiginfo; - -use std::sync::atomic::{AtomicBool, Ordering}; - -use libc::{c_int, siginfo_t}; - -mod sealed { - use std::fmt::Debug; - - use libc::{c_int, siginfo_t}; - - /// The actual implementation of the [`Exfiltrator`][super::Exfiltrator]. - /// - /// For now, this is hidden from the public API, but the intention is to move it to a public - /// place so users can implement it eventually, once we verify that it works well. - /// - /// # Safety - /// - /// The trait is unsafe as the [`Exfiltrator::store`] is called inside the signal handler and - /// must be async-signal-safe. Implementing this correctly may be difficult, therefore care - /// needs to be taken. One method known to work is encoding the data into an atomic variable. - /// Other, less limiting approaches, will be eventually explored. - pub unsafe trait Exfiltrator: Debug + Send + Sync + 'static { - /// One slot for storing the data. - /// - /// Each signal will get its one slot of this type, independent of other signals. It can - /// store the information in there inside the signal handler and will be loaded from it in - /// load. - /// - /// Each slot is initialized to the [`Default`] value. It is expected this value represents - /// „no signal delivered“ state. - type Storage: Debug + Default + Send + Sync + 'static; - - /// The type returned to the user. - type Output; - - /// If the given signal is supported by this specific exfiltrator. - /// - /// Not all information is available to all signals, therefore not all exfiltrators must - /// support all signals. If `false` is returned, the user is prevented for registering such - /// signal number with the given exfiltrator. - fn supports_signal(&self, sig: c_int) -> bool; - - /// Puts the signal information inside the slot. - /// - /// It needs to somehow store the relevant information and the fact that a signal happened. - /// - /// # Warning - /// - /// This will be called inside the signal handler. It needs to be async-signal-safe. In - /// particular, very small amount of operations are allowed in there. This namely does - /// *not* include any locking nor allocation. - /// - /// It is also possible that multiple store methods are called concurrently; it is up to - /// the implementor to deal with that. - fn store(&self, slot: &Self::Storage, signal: c_int, info: &siginfo_t); - - /// Loads the signal information from the given slot. - /// - /// The method shall check if the signal happened (it may be possible to be called without - /// the signal previously being delivered; it is up to the implementer to recognize it). It - /// is assumed the [`Default`] value is recognized as no signal delivered. - /// - /// If it was delivered, the method shall extract the relevant information *and reset the - /// slot* to the no signal delivered state. - /// - /// It shall return `Some(value)` if the signal was successfully received and `None` in - /// case no signal was delivered. - /// - /// No blocking shall happen inside this method. It may be called concurrently with - /// [`store`][Exfiltrator::store] (due to how signals work, concurrently even inside the - /// same thread ‒ a `store` may „interrupt“ a call to `load`). It is up to the implementer - /// to deal with that. - fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Self::Output>; - - /// Initialize the given slot for the given signal before the first use. - /// - /// This is called before the first use of the given slot (and it is annotated with the - /// corresponding signal). The default does nothing, this is just an opportunity to - /// allocate data lazily (this is called outside of the signal handler, so it doesn't have - /// to be async-signal-safe). It will be called at most once for each slot. - /// - /// Note that you can rely on this being called for correctness, but not for safety (this - /// crate calls it before the first use, but a user abusing the trait might not and in such - /// case it is OK to eg. lose signals, but not segfault). - fn init(&self, slot: &Self::Storage, signal: c_int) { - // Suppress unused variable warning without putting the underscores into public - // signature. - let _ = slot; - let _ = signal; - } - } -} - -/// A trait describing what and how is extracted from signal handlers. -/// -/// By choosing a specific implementor as the type parameter for -/// [`SignalsInfo`][crate::iterator::SignalsInfo], one can pick how much and what information is -/// returned from the iterator. -pub trait Exfiltrator: sealed::Exfiltrator {} - -impl<E: sealed::Exfiltrator> Exfiltrator for E {} - -/// An [`Exfiltrator`] providing just the signal numbers. -/// -/// This is the basic exfiltrator for most needs. For that reason, there's the -/// [`crate::iterator::Signals`] type alias, to simplify the type names for usual needs. -#[derive(Clone, Copy, Debug, Default)] -pub struct SignalOnly; - -unsafe impl sealed::Exfiltrator for SignalOnly { - type Storage = AtomicBool; - fn supports_signal(&self, _: c_int) -> bool { - true - } - type Output = c_int; - - fn store(&self, slot: &Self::Storage, _: c_int, _: &siginfo_t) { - slot.store(true, Ordering::SeqCst); - } - - fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Self::Output> { - if slot - .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed) - .is_ok() - { - Some(signal) - } else { - None - } - } -} diff --git a/vendor/signal-hook/src/iterator/exfiltrator/origin.rs b/vendor/signal-hook/src/iterator/exfiltrator/origin.rs deleted file mode 100644 index c3e2f15d2..000000000 --- a/vendor/signal-hook/src/iterator/exfiltrator/origin.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! An exfiltrator providing the process that caused the signal. -//! -//! The [`WithOrigin`] is an [`Exfiltrator`][crate::iterator::exfiltrator::Exfiltrator] that -//! provides the information about sending process in addition to the signal number, through the -//! [`Origin`] type. -//! -//! See the [`WithOrigin`] example. - -use libc::{c_int, siginfo_t}; - -pub use super::raw::Slot; -use super::sealed::Exfiltrator; -use super::WithRawSiginfo; -pub use crate::low_level::siginfo::{Origin, Process}; - -/// The [`Exfiltrator`][crate::iterator::exfiltrator::Exfiltrator] that produces [`Origin`] of -/// signals. -/// -/// # Examples -/// -/// ```rust -/// # use signal_hook::consts::SIGUSR1; -/// # use signal_hook::iterator::SignalsInfo; -/// # use signal_hook::iterator::exfiltrator::WithOrigin; -/// # -/// # fn main() -> Result<(), std::io::Error> { -/// // Subscribe to SIGUSR1, with information about the process. -/// let mut signals = SignalsInfo::<WithOrigin>::new(&[SIGUSR1])?; -/// -/// // Send a signal to ourselves. -/// let my_pid = unsafe { libc::getpid() }; -/// unsafe { libc::kill(my_pid, SIGUSR1) }; -/// -/// // Grab the signal and look into the details. -/// let received = signals.wait().next().unwrap(); -/// -/// assert_eq!(SIGUSR1, received.signal); -/// assert_eq!(my_pid, received.process.unwrap().pid); -/// # Ok(()) } -/// ``` -#[derive(Copy, Clone, Debug, Default)] -pub struct WithOrigin(WithRawSiginfo); - -// Safety: We need to be async-signal-safe. We delegate to other Exfiltrator, which already is and -// call a function that promises to be (Origin::extract) -unsafe impl Exfiltrator for WithOrigin { - type Storage = Slot; - type Output = Origin; - fn supports_signal(&self, signal: c_int) -> bool { - self.0.supports_signal(signal) - } - - fn store(&self, slot: &Slot, signal: c_int, info: &siginfo_t) { - self.0.store(slot, signal, info) - } - - fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Origin> { - self.0 - .load(slot, signal) - .map(|info| unsafe { Origin::extract(&info) }) - } - - fn init(&self, slot: &Self::Storage, signal: c_int) { - self.0.init(slot, signal) - } -} diff --git a/vendor/signal-hook/src/iterator/exfiltrator/raw.rs b/vendor/signal-hook/src/iterator/exfiltrator/raw.rs deleted file mode 100644 index 93c1ace6a..000000000 --- a/vendor/signal-hook/src/iterator/exfiltrator/raw.rs +++ /dev/null @@ -1,95 +0,0 @@ -//! An exfiltrator providing the raw [`siginfo_t`]. - -// Note on unsafety in this module: -// * Implementing an unsafe trait, that one needs to ensure at least store is async-signal-safe. -// That's done by delegating to the Channel (and reading an atomic pointer, but that one is -// primitive op). -// * A bit of juggling with atomic and raw pointers. In effect, that is just late lazy -// initialization, the Slot is in line with Option would be, except that it is set atomically -// during the init. Lifetime is ensured by not dropping until the Drop of the whole slot and that -// is checked by taking `&mut self`. - -use std::sync::atomic::{AtomicPtr, Ordering}; - -use libc::{c_int, siginfo_t}; - -use super::sealed::Exfiltrator; -use crate::low_level::channel::Channel; - -#[doc(hidden)] -#[derive(Default, Debug)] -pub struct Slot(AtomicPtr<Channel<siginfo_t>>); - -impl Drop for Slot { - fn drop(&mut self) { - let ptr = self.0.load(Ordering::Acquire); - if !ptr.is_null() { - drop(unsafe { Box::from_raw(ptr) }); - } - } -} - -/// The [`Exfiltrator`][crate::iterator::exfiltrator::Exfiltrator] that produces the raw -/// [`libc::siginfo_t`]. Note that it might look differently on different OSes and its API is a -/// little bit more limited than its C counterpart. -/// -/// You might prefer the [`WithOrigin`][super::WithOrigin] if you simply need information about the -/// origin of the signal. -/// -/// # Examples -/// -/// ```rust -/// # use signal_hook::consts::SIGUSR1; -/// # use signal_hook::iterator::SignalsInfo; -/// # use signal_hook::iterator::exfiltrator::WithRawSiginfo; -/// # -/// # fn main() -> Result<(), std::io::Error> { -/// // Subscribe to SIGUSR1, with information about the process. -/// let mut signals = SignalsInfo::<WithRawSiginfo>::new(&[SIGUSR1])?; -/// -/// // Send ourselves a signal. -/// signal_hook::low_level::raise(SIGUSR1)?; -/// -/// // Grab the signal and look into the details. -/// let received = signals.wait().next().unwrap(); -/// -/// // Not much else is useful in a cross-platform way :-( -/// assert_eq!(SIGUSR1, received.si_signo); -/// # Ok(()) } -/// ``` -#[derive(Copy, Clone, Debug, Default)] -pub struct WithRawSiginfo; - -unsafe impl Exfiltrator for WithRawSiginfo { - type Storage = Slot; - type Output = siginfo_t; - - fn supports_signal(&self, _: c_int) -> bool { - true - } - - fn store(&self, slot: &Slot, _: c_int, info: &siginfo_t) { - let info = *info; - // Condition just not to crash if someone forgot to call init. - // - // Lifetime is from init to our own drop, and drop needs &mut self. - if let Some(slot) = unsafe { slot.0.load(Ordering::Acquire).as_ref() } { - slot.send(info); - } - } - - fn load(&self, slot: &Slot, _: libc::c_int) -> Option<siginfo_t> { - let slot = unsafe { slot.0.load(Ordering::Acquire).as_ref() }; - // Condition just not to crash if someone forgot to call init. - slot.and_then(|s| s.recv()) - } - - fn init(&self, slot: &Self::Storage, _: c_int) { - let new = Box::default(); - let old = slot.0.swap(Box::into_raw(new), Ordering::Release); - // We leak the pointer on purpose here. This is invalid state anyway and must not happen, - // but if it still does, we can't drop that while some other thread might still be having - // the raw pointer. - assert!(old.is_null(), "Init called multiple times"); - } -} diff --git a/vendor/signal-hook/src/iterator/mod.rs b/vendor/signal-hook/src/iterator/mod.rs deleted file mode 100644 index b4bfec4e6..000000000 --- a/vendor/signal-hook/src/iterator/mod.rs +++ /dev/null @@ -1,323 +0,0 @@ -//! An iterator over incoming signals. -//! -//! This provides a higher abstraction over the signals, providing -//! the [`SignalsInfo`] structure which is able to iterate over the -//! incoming signals. The structure is parametrized by an -//! [`Exfiltrator`][self::exfiltrator::Exfiltrator], which specifies what information is returned -//! for each delivered signal. Note that some exfiltrators are behind a feature flag. -//! -//! The [`Signals`] is a type alias for the common case when it is enough to get the signal number. -//! -//! This module (and everything in it) is turned by the `iterator` feature. It is **on** by -//! default, the possibility to turn off is mostly possible for very special purposes (compiling on -//! `<rustc-1.36`, minimizing the amount of code compiled, …). In a sense, this is the highest -//! level abstraction of the crate and the API expected to be used by most of the people. -//! -//! # Examples -//! -//! ```rust -//! extern crate libc; -//! extern crate signal_hook; -//! -//! use std::io::Error; -//! -//! use signal_hook::consts::signal::*; -//! use signal_hook::iterator::Signals; -//! -//! fn main() -> Result<(), Error> { -//! let mut signals = Signals::new(&[ -//! SIGHUP, -//! SIGTERM, -//! SIGINT, -//! SIGQUIT, -//! # SIGUSR1, -//! ])?; -//! # // A trick to terminate the example when run as doc-test. Not part of the real code. -//! # signal_hook::low_level::raise(SIGUSR1).unwrap(); -//! 'outer: loop { -//! // Pick up signals that arrived since last time -//! for signal in signals.pending() { -//! match signal as libc::c_int { -//! SIGHUP => { -//! // Reload configuration -//! // Reopen the log file -//! } -//! SIGTERM | SIGINT | SIGQUIT => { -//! break 'outer; -//! }, -//! # SIGUSR1 => return Ok(()), -//! _ => unreachable!(), -//! } -//! } -//! // Do some bit of work ‒ something with upper limit on waiting, so we don't block -//! // forever with a SIGTERM already waiting. -//! } -//! println!("Terminating. Bye bye"); -//! Ok(()) -//! } -//! ``` - -pub mod backend; -pub mod exfiltrator; - -use std::borrow::Borrow; -use std::fmt::{Debug, Formatter, Result as FmtResult}; -use std::io::{Error, ErrorKind, Read}; -use std::os::unix::net::UnixStream; - -use libc::{self, c_int}; - -pub use self::backend::{Handle, Pending}; -use self::backend::{PollResult, RefSignalIterator, SignalDelivery}; -use self::exfiltrator::{Exfiltrator, SignalOnly}; - -/// The main structure of the module, representing interest in some signals. -/// -/// Unlike the helpers in other modules, this registers the signals when created and unregisters -/// them on drop. It provides the pending signals during its lifetime, either in batches or as an -/// infinite iterator. -/// -/// Most users will want to use it through the [`Signals`] type alias for simplicity. -/// -/// # Multiple threads -/// -/// Instances of this struct can be [sent][std::marker::Send] to other threads. In a multithreaded -/// application this can be used to dedicate a separate thread for signal handling. In this case -/// you should get a [`Handle`] using the [`handle`][Signals::handle] method before sending the -/// `Signals` instance to a background thread. With the handle you will be able to shut down the -/// background thread later, or to operatively add more signals. -/// -/// The controller handle can be shared between as many threads as you like using its -/// [`clone`][Handle::clone] method. -/// -/// # Exfiltrators -/// -/// The [`SignalOnly]` provides only the signal number. There are further exfiltrators available in -/// the [`exfiltrator`] module. Note that some of them are behind feature flags that need to be -/// enabled. -/// -/// # Examples -/// -/// ```rust -/// # extern crate signal_hook; -/// # -/// # use std::io::Error; -/// # use std::thread; -/// use signal_hook::consts::signal::*; -/// use signal_hook::iterator::Signals; -/// -/// # -/// # fn main() -> Result<(), Error> { -/// let mut signals = Signals::new(&[SIGUSR1, SIGUSR2])?; -/// let handle = signals.handle(); -/// let thread = thread::spawn(move || { -/// for signal in &mut signals { -/// match signal { -/// SIGUSR1 => {}, -/// SIGUSR2 => {}, -/// _ => unreachable!(), -/// } -/// } -/// }); -/// -/// // Some time later... -/// handle.close(); -/// thread.join().unwrap(); -/// # Ok(()) -/// # } -/// ``` -pub struct SignalsInfo<E: Exfiltrator = SignalOnly>(SignalDelivery<UnixStream, E>); - -impl<E: Exfiltrator> SignalsInfo<E> { - /// Creates the `Signals` structure. - /// - /// This registers all the signals listed. The same restrictions (panics, errors) apply as - /// for the [`Handle::add_signal`] method. - pub fn new<I, S>(signals: I) -> Result<Self, Error> - where - I: IntoIterator<Item = S>, - S: Borrow<c_int>, - E: Default, - { - Self::with_exfiltrator(signals, E::default()) - } - - /// An advanced constructor with explicit [`Exfiltrator`]. - pub fn with_exfiltrator<I, S>(signals: I, exfiltrator: E) -> Result<Self, Error> - where - I: IntoIterator<Item = S>, - S: Borrow<c_int>, - { - let (read, write) = UnixStream::pair()?; - Ok(SignalsInfo(SignalDelivery::with_pipe( - read, - write, - exfiltrator, - signals, - )?)) - } - - /// Registers another signal to the set watched by this [`Signals`] instance. - /// - /// The same restrictions (panics, errors) apply as for the [`Handle::add_signal`] - /// method. - pub fn add_signal(&self, signal: c_int) -> Result<(), Error> { - self.handle().add_signal(signal) - } - - /// Returns an iterator of already received signals. - /// - /// This returns an iterator over all the signal numbers of the signals received since last - /// time they were read (out of the set registered by this `Signals` instance). Note that they - /// are returned in arbitrary order and a signal instance may returned only once even if it was - /// received multiple times. - /// - /// This method returns immediately (does not block) and may produce an empty iterator if there - /// are no signals ready. - pub fn pending(&mut self) -> Pending<E> { - self.0.pending() - } - - /// Block until the stream contains some bytes. - /// - /// Returns true if it was possible to read a byte and false otherwise. - fn has_signals(read: &mut UnixStream) -> Result<bool, Error> { - loop { - match read.read(&mut [0u8]) { - Ok(num_read) => break Ok(num_read > 0), - // If we get an EINTR error it is fine to retry reading from the stream. - // Otherwise we should pass on the error to the caller. - Err(error) => { - if error.kind() != ErrorKind::Interrupted { - break Err(error); - } - } - } - } - } - - /// Waits for some signals to be available and returns an iterator. - /// - /// This is similar to [`pending`][SignalsInfo::pending]. If there are no signals available, it - /// tries to wait for some to arrive. However, due to implementation details, this still can - /// produce an empty iterator. - /// - /// This can block for arbitrary long time. If the [`Handle::close`] method is used in - /// another thread this method will return immediately. - /// - /// Note that the blocking is done in this method, not in the iterator. - pub fn wait(&mut self) -> Pending<E> { - match self.0.poll_pending(&mut Self::has_signals) { - Ok(Some(pending)) => pending, - // Because of the blocking has_signals method the poll_pending method - // only returns None if the instance is closed. But we want to return - // a possibly empty pending object anyway. - Ok(None) => self.pending(), - // Users can't manipulate the internal file descriptors and the way we use them - // shouldn't produce any errors. So it is OK to panic. - Err(error) => panic!("Unexpected error: {}", error), - } - } - - /// Is it closed? - /// - /// See [`close`][Handle::close]. - pub fn is_closed(&self) -> bool { - self.handle().is_closed() - } - - /// Get an infinite iterator over arriving signals. - /// - /// The iterator's `next()` blocks as necessary to wait for signals to arrive. This is adequate - /// if you want to designate a thread solely to handling signals. If multiple signals come at - /// the same time (between two values produced by the iterator), they will be returned in - /// arbitrary order. Multiple instances of the same signal may be collated. - /// - /// This is also the iterator returned by `IntoIterator` implementation on `&mut Signals`. - /// - /// This iterator terminates only if explicitly [closed][Handle::close]. - /// - /// # Examples - /// - /// ```rust - /// # extern crate libc; - /// # extern crate signal_hook; - /// # - /// # use std::io::Error; - /// # use std::thread; - /// # - /// use signal_hook::consts::signal::*; - /// use signal_hook::iterator::Signals; - /// - /// # fn main() -> Result<(), Error> { - /// let mut signals = Signals::new(&[SIGUSR1, SIGUSR2])?; - /// let handle = signals.handle(); - /// thread::spawn(move || { - /// for signal in signals.forever() { - /// match signal { - /// SIGUSR1 => {}, - /// SIGUSR2 => {}, - /// _ => unreachable!(), - /// } - /// } - /// }); - /// handle.close(); - /// # Ok(()) - /// # } - /// ``` - pub fn forever(&mut self) -> Forever<E> { - Forever(RefSignalIterator::new(&mut self.0)) - } - - /// Get a shareable handle to a [`Handle`] for this instance. - /// - /// This can be used to add further signals or close the [`Signals`] instance. - pub fn handle(&self) -> Handle { - self.0.handle() - } -} - -impl<E> Debug for SignalsInfo<E> -where - E: Debug + Exfiltrator, - E::Storage: Debug, -{ - fn fmt(&self, fmt: &mut Formatter) -> FmtResult { - fmt.debug_tuple("Signals").field(&self.0).finish() - } -} - -impl<'a, E: Exfiltrator> IntoIterator for &'a mut SignalsInfo<E> { - type Item = E::Output; - type IntoIter = Forever<'a, E>; - fn into_iter(self) -> Self::IntoIter { - self.forever() - } -} - -/// An infinit iterator of arriving signals. -pub struct Forever<'a, E: Exfiltrator>(RefSignalIterator<'a, UnixStream, E>); - -impl<'a, E: Exfiltrator> Iterator for Forever<'a, E> { - type Item = E::Output; - - fn next(&mut self) -> Option<E::Output> { - match self.0.poll_signal(&mut SignalsInfo::<E>::has_signals) { - PollResult::Signal(result) => Some(result), - PollResult::Closed => None, - PollResult::Pending => unreachable!( - "Because of the blocking has_signals method the \ - poll_signal method never returns Poll::Pending but blocks until a signal arrived" - ), - // Users can't manipulate the internal file descriptors and the way we use them - // shouldn't produce any errors. So it is OK to panic. - PollResult::Err(error) => panic!("Unexpected error: {}", error), - } - } -} - -/// A type alias for an iterator returning just the signal numbers. -/// -/// This is the simplified version for most of the use cases. For advanced usages, the -/// [`SignalsInfo`] with explicit [`Exfiltrator`] type can be used. -pub type Signals = SignalsInfo<SignalOnly>; diff --git a/vendor/signal-hook/src/lib.rs b/vendor/signal-hook/src/lib.rs deleted file mode 100644 index d750e15c2..000000000 --- a/vendor/signal-hook/src/lib.rs +++ /dev/null @@ -1,414 +0,0 @@ -#![doc( - test(attr(deny(warnings))), - test(attr(allow(bare_trait_objects, unknown_lints))) -)] -#![warn(missing_docs)] -// Don't fail on links to things not enabled in features -#![allow( - unknown_lints, - renamed_and_removed_lints, - intra_doc_link_resolution_failure, - broken_intra_doc_links -)] -// These little nifty labels saying that something needs a feature to be enabled -#![cfg_attr(docsrs, feature(doc_cfg))] -//! Library for easier and safe Unix signal handling -//! -//! Unix signals are inherently hard to handle correctly, for several reasons: -//! -//! * They are a global resource. If a library wants to set its own signal handlers, it risks -//! disrupting some other library. It is possible to chain the previous signal handler, but then -//! it is impossible to remove the old signal handlers from the chains in any practical manner. -//! * They can be called from whatever thread, requiring synchronization. Also, as they can -//! interrupt a thread at any time, making most handling race-prone. -//! * According to the POSIX standard, the set of functions one may call inside a signal handler is -//! limited to very few of them. To highlight, mutexes (or other locking mechanisms) and memory -//! allocation and deallocation is *not* allowed. -//! -//! # The goal of the library -//! -//! The aim is to subscriptions to signals a „structured“ resource, in a similar way memory -//! allocation is ‒ parts of the program can independently subscribe and it's the same part of the -//! program that can give them up, independently of what the other parts do. Therefore, it is -//! possible to register multiple actions to the same signal. -//! -//! Another goal is to shield applications away from differences between platforms. Various Unix -//! systems have little quirks and differences that need to be worked around and that's not -//! something every application should be dealing with. We even try to provide some support for -//! Windows, but we lack the expertise in that area, so that one is not complete and is a bit rough -//! (if you know how it works there and are willing to either contribute the code or consult, -//! please get in touch). -//! -//! Furthermore, it provides implementation of certain common signal-handling patterns, usable from -//! safe Rust, without the application author needing to learn about *all* the traps. -//! -//! Note that despite everything, there are still some quirks around signal handling that are not -//! possible to paper over and need to be considered. Also, there are some signal use cases that -//! are inherently unsafe and they are not covered by this crate. -//! -//! # Anatomy of the crate -//! -//! The crate is split into several modules. -//! -//! The easiest way to handle signals is using the [`Signals`][crate::iterator::Signals] iterator -//! thing. It can register for a set of signals and produce them one by one, in a blocking manner. -//! You can reserve a thread for handling them as they come. If you want something asynchronous, -//! there are adaptor crates for the most common asynchronous runtimes. The module also contains -//! ways to build iterators that produce a bit more information that just the signal number. -//! -//! The [`flag`] module contains routines to set a flag based on incoming signals and to do -//! certain actions inside the signal handlers based on the flags (the flags can also be -//! manipulated by the rest of the application). This allows building things like checking if a -//! signal happened on each loop iteration or making sure application shuts down on the second -//! CTRL+C if it got stuck in graceful shutdown requested by the first. -//! -//! The [`consts`] module contains some constants, most importantly the signal numbers themselves -//! (these are just re-exports from [`libc`] and if your OS has some extra ones, you can use them -//! too, this is just for convenience). -//! -//! And last, there is the [`low_level`] module. It contains routines to directly register and -//! unregister arbitrary actions. Some of the patters in the above modules return a [`SigId`], -//! which can be used with the [`low_level::unregister`] to remove the action. There are also some -//! other utilities that are more suited to build other abstractions with than to use directly. -//! -//! Certain parts of the library can be enabled or disabled with use flags: -//! -//! * `channel`: The [low_level::channel] module (on by default). -//! * `iterator`: The [iterator] module (on by default). -//! * `extended-sig-info`: Support for providing more information in the iterators or from the -//! async adaptor crates. This is off by default. -//! -//! # Limitations -//! -//! * OS limitations still apply. Certain signals are not possible to override or subscribe to ‒ -//! `SIGKILL` or `SIGSTOP`. -//! * Overriding some others is probably a very stupid idea (or very unusual needs) ‒ handling eg. -//! `SIGSEGV` is not something done lightly. For that reason, the crate will panic in case -//! registering of these is attempted (see [`FORBIDDEN`][crate::consts::FORBIDDEN]. If you still -//! need to do so, you can find such APIs in the `signal-hook-registry` backend crate, but -//! additional care must be taken. -//! * Interaction with other signal-handling libraries is limited. If signal-hook finds an existing -//! handler present, it chain-calls it from the signal it installs and assumes other libraries -//! would do the same, but that's everything that can be done to make it work with libraries not -//! based on [`signal-hook-registry`](https://lib.rs/signal-hook-registry) -//! (the backend of this crate). -//! * The above chaining contains a race condition in multi-threaded programs, where the previous -//! handler might not get called if it is received during the registration process. This is -//! handled (at least on non-windows platforms) on the same thread where the registration -//! happens, therefore it is advised to register at least one action for each signal of interest -//! early, before any additional threads are started. Registering any additional (or removing and -//! registering again) action on the same signal is without the race condition. -//! * Once at least one action is registered for a signal, the default action is replaced (this is -//! how signals work in the OS). Even if all actions of that signal are removed, `signal-hook` -//! does not restore the default handler (such behaviour would be at times inconsistent with -//! making the actions independent and there's no reasonable way to do so in a race-free way in a -//! multi-threaded program while also dealing with signal handlers registered with other -//! libraries). It is, however, possible to *emulate* the default handler (see the -//! [`emulate_default_handler`][low_level::emulate_default_handler]) ‒ there are only 4 -//! default handlers: -//! - Ignore. This is easy to emulate. -//! - Abort. Depending on if you call it from within a signal handler of from outside, the -//! [`low_level::abort`] or [`std::process::abort`] can be used. -//! - Terminate. This can be done with `exit` ([`low_level::exit`] or [`std::process::exit`]). -//! - Stop. It is possible to [`raise`][low_level::raise] the [`SIGSTOP`][consts::SIGSTOP] signal. -//! That one can't be replaced and always stops the application. -//! * Many of the patterns here can collate multiple instances of the same signal into fewer -//! instances, if the application doesn't consume them fast enough. This is consistent with what -//! the kernel does if the application doesn't keep up with them (at least for non-realtime -//! signals, see below), so it is something one needs to deal with anyway. -//! * (By design) the library mostly _postpones_ or helps the user postpone acting on the signals -//! until later. This, in combination with the above collating inside the library may make it -//! unsuitable for realtime signals. These usually want to be handled directly inside the signal -//! handler ‒ which still can be done with [signal_hook_registry::register], but using unsafe and -//! due care. Patterns for working safely with realtime signals are not unwanted in the library, -//! but nobody contributed them yet. -//! -//! # Signal masks -//! -//! As the library uses `sigaction` under the hood, signal masking works as expected (eg. with -//! `pthread_sigmask`). This means, signals will *not* be delivered if the signal is masked in all -//! program's threads. -//! -//! By the way, if you do want to modify the signal mask (or do other Unix-specific magic), the -//! [nix](https://lib.rs/crates/nix) crate offers safe interface to many low-level functions, -//! including -//! [`pthread_sigmask`](https://docs.rs/nix/0.11.0/nix/sys/signal/fn.pthread_sigmask.html). -//! -//! # Portability -//! -//! It should work on any POSIX.1-2001 system, which are all the major big OSes with the notable -//! exception of Windows. -//! -//! Non-standard signals are also supported. Pass the signal value directly from `libc` or use -//! the numeric value directly. -//! -//! ```rust -//! use std::sync::Arc; -//! use std::sync::atomic::{AtomicBool}; -//! let term = Arc::new(AtomicBool::new(false)); -//! let _ = signal_hook::flag::register(libc::SIGINT, Arc::clone(&term)); -//! ``` -//! -//! This crate includes a limited support for Windows, based on `signal`/`raise` in the CRT. -//! There are differences in both API and behavior: -//! -//! - Many parts of the library are not available there. -//! - We have only a few signals: `SIGABRT`, `SIGABRT_COMPAT`, `SIGBREAK`, -//! `SIGFPE`, `SIGILL`, `SIGINT`, `SIGSEGV` and `SIGTERM`. -//! - Due to lack of signal blocking, there's a race condition. -//! After the call to `signal`, there's a moment where we miss a signal. -//! That means when you register a handler, there may be a signal which invokes -//! neither the default handler or the handler you register. -//! - Handlers registered by `signal` in Windows are cleared on first signal. -//! To match behavior in other platforms, we re-register the handler each time the handler is -//! called, but there's a moment where we miss a handler. -//! That means when you receive two signals in a row, there may be a signal which invokes -//! the default handler, nevertheless you certainly have registered the handler. -//! -//! Moreover, signals won't work as you expected. `SIGTERM` isn't actually used and -//! not all `Ctrl-C`s are turned into `SIGINT`. -//! -//! Patches to improve Windows support in this library are welcome. -//! -//! # Features -//! -//! There are several feature flags that control how much is available as part of the crate, some -//! enabled by default. -//! -//! * `channel`: (enabled by default) The [Channel][crate::low_level::channel] synchronization -//! primitive for exporting data out of signal handlers. -//! * `iterator`: (enabled by default) An [Signals iterator][crate::iterator::Signals] that -//! provides a convenient interface for receiving signals in rust-friendly way. -//! * `extended-siginfo` adds support for providing extra information as part of the iterator -//! interface. -//! -//! # Examples -//! -//! ## Using a flag to terminate a loop-based application -//! -//! ```rust -//! use std::io::Error; -//! use std::sync::Arc; -//! use std::sync::atomic::{AtomicBool, Ordering}; -//! -//! fn main() -> Result<(), Error> { -//! let term = Arc::new(AtomicBool::new(false)); -//! signal_hook::flag::register(signal_hook::consts::SIGTERM, Arc::clone(&term))?; -//! while !term.load(Ordering::Relaxed) { -//! // Do some time-limited stuff here -//! // (if this could block forever, then there's no guarantee the signal will have any -//! // effect). -//! # -//! # // Hack to terminate the example, not part of the real code. -//! # term.store(true, Ordering::Relaxed); -//! } -//! Ok(()) -//! } -//! ``` -//! -//! ## A complex signal handling with a background thread -//! -//! This also handles the double CTRL+C situation (eg. the second CTRL+C kills) and resetting the -//! terminal on `SIGTSTP` (CTRL+Z, curses-based applications should do something like this). -//! -//! ```rust -//! # #[cfg(feature = "extended-siginfo")] pub mod test { -//! use std::io::Error; -//! use std::sync::Arc; -//! use std::sync::atomic::AtomicBool; -//! -//! use signal_hook::consts::signal::*; -//! use signal_hook::consts::TERM_SIGNALS; -//! use signal_hook::flag; -//! // A friend of the Signals iterator, but can be customized by what we want yielded about each -//! // signal. -//! use signal_hook::iterator::SignalsInfo; -//! use signal_hook::iterator::exfiltrator::WithOrigin; -//! use signal_hook::low_level; -//! -//! # struct App; -//! # impl App { -//! # fn run_background() -> Self { Self } -//! # fn wait_for_stop(self) {} -//! # fn restore_term(&self) {} -//! # fn claim_term(&self) {} -//! # fn resize_term(&self) {} -//! # fn reload_config(&self) {} -//! # fn print_stats(&self) {} -//! # } -//! # pub -//! fn main() -> Result<(), Error> { -//! // Make sure double CTRL+C and similar kills -//! let term_now = Arc::new(AtomicBool::new(false)); -//! for sig in TERM_SIGNALS { -//! // When terminated by a second term signal, exit with exit code 1. -//! // This will do nothing the first time (because term_now is false). -//! flag::register_conditional_shutdown(*sig, 1, Arc::clone(&term_now))?; -//! // But this will "arm" the above for the second time, by setting it to true. -//! // The order of registering these is important, if you put this one first, it will -//! // first arm and then terminate ‒ all in the first round. -//! flag::register(*sig, Arc::clone(&term_now))?; -//! } -//! -//! // Subscribe to all these signals with information about where they come from. We use the -//! // extra info only for logging in this example (it is not available on all the OSes or at -//! // all the occasions anyway, it may return `Unknown`). -//! let mut sigs = vec![ -//! // Some terminal handling -//! SIGTSTP, SIGCONT, SIGWINCH, -//! // Reload of configuration for daemons ‒ um, is this example for a TUI app or a daemon -//! // O:-)? You choose... -//! SIGHUP, -//! // Application-specific action, to print some statistics. -//! SIGUSR1, -//! ]; -//! sigs.extend(TERM_SIGNALS); -//! let mut signals = SignalsInfo::<WithOrigin>::new(&sigs)?; -//! # low_level::raise(SIGTERM)?; // Trick to terminate the example -//! -//! // This is the actual application that'll start in its own thread. We'll control it from -//! // this thread based on the signals, but it keeps running. -//! // This is called after all the signals got registered, to avoid the short race condition -//! // in the first registration of each signal in multi-threaded programs. -//! let app = App::run_background(); -//! -//! // Consume all the incoming signals. This happens in "normal" Rust thread, not in the -//! // signal handlers. This means that we are allowed to do whatever we like in here, without -//! // restrictions, but it also means the kernel believes the signal already got delivered, we -//! // handle them in delayed manner. This is in contrast with eg the above -//! // `register_conditional_shutdown` where the shutdown happens *inside* the handler. -//! let mut has_terminal = true; -//! for info in &mut signals { -//! // Will print info about signal + where it comes from. -//! eprintln!("Received a signal {:?}", info); -//! match info.signal { -//! SIGTSTP => { -//! // Restore the terminal to non-TUI mode -//! if has_terminal { -//! app.restore_term(); -//! has_terminal = false; -//! // And actually stop ourselves. -//! low_level::emulate_default_handler(SIGTSTP)?; -//! } -//! } -//! SIGCONT => { -//! if !has_terminal { -//! app.claim_term(); -//! has_terminal = true; -//! } -//! } -//! SIGWINCH => app.resize_term(), -//! SIGHUP => app.reload_config(), -//! SIGUSR1 => app.print_stats(), -//! term_sig => { // These are all the ones left -//! eprintln!("Terminating"); -//! assert!(TERM_SIGNALS.contains(&term_sig)); -//! break; -//! } -//! } -//! } -//! -//! // If during this another termination signal comes, the trick at the top would kick in and -//! // terminate early. But if it doesn't, the application shuts down gracefully. -//! app.wait_for_stop(); -//! -//! Ok(()) -//! } -//! # } -//! # fn main() { -//! # #[cfg(feature = "extended-siginfo")] test::main().unwrap(); -//! # } -//! ``` -//! -//! # Asynchronous runtime support -//! -//! If you are looking for integration with an asynchronous runtime take a look at one of the -//! following adapter crates: -//! -//! * [`signal-hook-async-std`](https://docs.rs/signal-hook-async-std) for async-std support -//! * [`signal-hook-mio`](https://docs.rs/signal-hook-mio) for MIO support -//! * [`signal-hook-tokio`](https://docs.rs/signal-hook-tokio) for Tokio support -//! -//! Feel free to open a pull requests if you want to add support for runtimes not mentioned above. -//! -//! # Porting from previous versions -//! -//! There were some noisy changes when going from 0.2 version to the 0.3 version. In particular: -//! -//! * A lot of things moved around to make the structure of the crate a bit more understandable. -//! Most of the time it should be possible to just search the documentation for the name that -//! can't be resolved to discover the new location. -//! - The signal constants (`SIGTERM`, for example) are in [`consts`] submodule (individual -//! imports) and in the [`consts::signal`] (for wildcard import of all of them). -//! - Some APIs that are considered more of a low-level building blocks than for casual day to -//! day use are now in the [`low_level`] submodule. -//! * The previous version contained the `cleanup` module that allowed for removal of the actions -//! in rather destructive way (nuking actions of arbitrary other parts of the program). This is -//! completely gone in this version. The use case of shutting down the application on second -//! CTRL+C is now supported by a pattern described in the [`flag`] submodule. For other similar -//! needs, refer above for emulating default handlers. - -pub mod flag; -#[cfg(all(not(windows), feature = "iterator"))] -#[cfg_attr(docsrs, doc(cfg(all(not(windows), feature = "iterator"))))] -pub mod iterator; -pub mod low_level; - -/// The low-level constants. -/// -/// Like the signal numbers. -pub mod consts { - - use libc::c_int; - - /// The signal constants. - /// - /// Can be mass-imported by `use signal_hook::consts::signal::*`, without polluting the - /// namespace with other names. Also available in the [`consts`][crate::consts] directly (but - /// with more constants around). - pub mod signal { - #[cfg(not(windows))] - pub use libc::{ - SIGABRT, SIGALRM, SIGBUS, SIGCHLD, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, - SIGPIPE, SIGPROF, SIGQUIT, SIGSEGV, SIGSTOP, SIGSYS, SIGTERM, SIGTRAP, SIGTSTP, - SIGTTIN, SIGTTOU, SIGURG, SIGUSR1, SIGUSR2, SIGVTALRM, SIGWINCH, SIGXCPU, SIGXFSZ, - }; - - #[cfg(not(any(windows, target_os = "haiku")))] - pub use libc::SIGIO; - - #[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "netbsd", - target_os = "openbsd", - target_os = "macos" - ))] - pub use libc::SIGINFO; - - #[cfg(windows)] - pub use libc::{SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM}; - - // NOTE: they perhaps deserve backport to libc. - #[cfg(windows)] - /// Same as `SIGABRT`, but the number is compatible to other platforms. - pub const SIGABRT_COMPAT: libc::c_int = 6; - #[cfg(windows)] - /// Ctrl-Break is pressed for Windows Console processes. - pub const SIGBREAK: libc::c_int = 21; - } - - pub use self::signal::*; - - pub use signal_hook_registry::FORBIDDEN; - - /// Various signals commonly requesting shutdown of an application. - #[cfg(not(windows))] - pub const TERM_SIGNALS: &[c_int] = &[SIGTERM, SIGQUIT, SIGINT]; - - /// Various signals commonly requesting shutdown of an application. - #[cfg(windows)] - pub const TERM_SIGNALS: &[c_int] = &[SIGTERM, SIGINT]; -} - -pub use signal_hook_registry::SigId; diff --git a/vendor/signal-hook/src/low_level/channel.rs b/vendor/signal-hook/src/low_level/channel.rs deleted file mode 100644 index cc46c836f..000000000 --- a/vendor/signal-hook/src/low_level/channel.rs +++ /dev/null @@ -1,235 +0,0 @@ -//! A restricted channel to pass data from signal handler. -//! -//! When trying to communicate data from signal handler to the outside world, one can use an atomic -//! variable (as it doesn't lock, so it can be made async-signal-safe). But this won't work for -//! larger data. -//! -//! This module provides a channel that can be used for that purpose. It is used by certain -//! [exfiltrators][crate::iterator::exfiltrator], but can be used as building block for custom -//! actions. In general, this is not a ready-made end-user API. -//! -//! # How does it work -//! -//! Each channel has a fixed number of slots and two queues (one for empty slots, one for full -//! slots). A signal handler takes a slot out of the empty one, fills it and passes it into the -//! full one. Outside of signal handler, it can take the value out of the full queue and return the -//! slot to the empty queue. -//! -//! The queues are implemented as bit-encoded indexes of the slots in the storage. The bits are -//! stored in an atomic variable. -//! -//! Note that the algorithm allows for a slot to be in neither queue (when it is being emptied or -//! filled). -//! -//! # Fallible allocation of a slot -//! -//! It is apparent that allocation of a new slot can fail (there's nothing in the empty slot). In -//! such case, there's no way to send the new value out of the handler (there's no way to safely -//! wait for a slot to appear, because the handler can be blocking the thread that is responsible -//! for emptying them). But that's considered acceptable ‒ even the kernel collates the same kinds -//! of signals together if they are not consumed by application fast enough and there are no free -//! slots exactly because some are being filled, emptied or are full ‒ in particular, the whole -//! system will yield a signal. -//! -//! This assumes that separate signals don't share the same buffer and that there's only one reader -//! (using multiple readers is still safe, but it is possible that all slots would be inside the -//! readers, but already empty, so the above argument would not hold). - -// TODO: Other sizes? Does anyone need more than 5 slots? - -use std::cell::UnsafeCell; -use std::sync::atomic::{AtomicU16, Ordering}; - -const SLOTS: usize = 5; -const BITS: u16 = 3; -const MASK: u16 = 0b111; - -fn get(n: u16, idx: u16) -> u16 { - (n >> (BITS * idx)) & MASK -} - -fn set(n: u16, idx: u16, v: u16) -> u16 { - let v = v << (BITS * idx); - let mask = MASK << (BITS * idx); - (n & !mask) | v -} - -fn enqueue(q: &AtomicU16, val: u16) { - let mut current = q.load(Ordering::Relaxed); - loop { - let empty = (0..SLOTS as u16) - .find(|i| get(current, *i) == 0) - .expect("No empty slot available"); - let modified = set(current, empty, val); - match q.compare_exchange_weak(current, modified, Ordering::Release, Ordering::Relaxed) { - Ok(_) => break, - Err(changed) => current = changed, // And retry with the changed value - } - } -} - -fn dequeue(q: &AtomicU16) -> Option<u16> { - let mut current = q.load(Ordering::Relaxed); - loop { - let val = current & MASK; - // It's completely empty - if val == 0 { - break None; - } - let modified = current >> BITS; - match q.compare_exchange_weak(current, modified, Ordering::Acquire, Ordering::Relaxed) { - Ok(_) => break Some(val), - Err(changed) => current = changed, - } - } -} - -/// A restricted async-signal-safe channel -/// -/// This is a bit like the usual channel used for inter-thread communication, but with several -/// restrictions: -/// -/// * There's a limited number of slots (currently 5). -/// * There's no way to wait for a place in it or for a value. If value is not available, `None` is -/// returned. If there's no space for a value, the value is silently dropped. -/// -/// In exchange for that, all the operations on that channel are async-signal-safe. That means it -/// is possible to use it to communicate between a signal handler and the rest of the world with it -/// (specifically, it's designed to send information from the handler to the rest of the -/// application). The throwing out of values when full is in line with collating of the same type -/// in kernel (you should not use the same channel for multiple different signals). -/// -/// Technically, this is a MPMC queue which preserves order, but it is expected to be used in MPSC -/// mode mostly (in theory, multiple threads can be executing a signal handler for the same signal -/// at the same time). The channel is not responsible for wakeups. -/// -/// While the channel is async-signal-safe, you still need to make sure *creating* of the values is -/// too (it should not contain anything that allocates, for example ‒ so no `String`s inside, etc). -/// -/// The code was *not* tuned for performance (signals are not expected to happen often). -pub struct Channel<T> { - storage: [UnsafeCell<Option<T>>; SLOTS], - empty: AtomicU16, - full: AtomicU16, -} - -impl<T> Channel<T> { - /// Creates a new channel with nothing in it. - pub fn new() -> Self { - let storage = Default::default(); - let me = Self { - storage, - empty: AtomicU16::new(0), - full: AtomicU16::new(0), - }; - - for i in 1..SLOTS + 1 { - enqueue(&me.empty, i as u16); - } - - me - } - - /// Inserts a value into the channel. - /// - /// If the value doesn't fit, it is silently dropped. Never blocks. - pub fn send(&self, val: T) { - if let Some(empty_idx) = dequeue(&self.empty) { - unsafe { *self.storage[empty_idx as usize - 1].get() = Some(val) }; - enqueue(&self.full, empty_idx); - } - } - - /// Takes a value from the channel. - /// - /// Or returns `None` if the channel is empty. Never blocks. - pub fn recv(&self) -> Option<T> { - dequeue(&self.full).map(|idx| { - let result = unsafe { &mut *self.storage[idx as usize - 1].get() } - .take() - .expect("Full slot with nothing in it"); - enqueue(&self.empty, idx); - result - }) - } -} - -impl<T> Default for Channel<T> { - fn default() -> Self { - Self::new() - } -} - -unsafe impl<T: Send> Send for Channel<T> {} - -// Yes, really Send -> Sync. Having a reference to Channel allows Sending Ts, but not having refs -// on them. -unsafe impl<T: Send> Sync for Channel<T> {} - -#[cfg(test)] -mod tests { - use std::sync::Arc; - use std::thread; - - use super::*; - - #[test] - fn new_empty() { - let channel = Channel::<usize>::new(); - assert!(channel.recv().is_none()); - assert!(channel.recv().is_none()); - } - - #[test] - fn pass_value() { - let channel = Channel::new(); - channel.send(42); - assert_eq!(42, channel.recv().unwrap()); - assert!(channel.recv().is_none()); - } - - #[test] - fn multiple() { - let channel = Channel::new(); - for i in 0..1000 { - channel.send(i); - assert_eq!(i, channel.recv().unwrap()); - assert!(channel.recv().is_none()); - } - } - - #[test] - fn overflow() { - let channel = Channel::new(); - for i in 0..10 { - channel.send(i); - } - for i in 0..5 { - assert_eq!(i, channel.recv().unwrap()); - } - assert!(channel.recv().is_none()); - } - - #[test] - fn multi_thread() { - let channel = Arc::new(Channel::<usize>::new()); - - let sender = thread::spawn({ - let channel = Arc::clone(&channel); - move || { - for i in 0..4 { - channel.send(i); - } - } - }); - - let mut results = Vec::new(); - while results.len() < 4 { - results.extend(channel.recv()); - } - - assert_eq!(vec![0, 1, 2, 3], results); - - sender.join().unwrap(); - } -} diff --git a/vendor/signal-hook/src/low_level/extract.c b/vendor/signal-hook/src/low_level/extract.c deleted file mode 100644 index 5f226158b..000000000 --- a/vendor/signal-hook/src/low_level/extract.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Low-level extraction code to overcome rust's libc not having the best access - * to siginfo_t details. - */ -#include <stdbool.h> -#include <signal.h> -#include <stdint.h> - -struct Const { - int native; - // The signal this applies to, or -1 if it applies to anything. - int signal; - uint8_t translated; -}; - -// Warning: must be in sync with the rust source code -struct Const consts[] = { -#ifdef SI_KERNEL - { SI_KERNEL, -1, 1 }, -#endif - { SI_USER, -1, 2 }, -#ifdef SI_TKILL - { SI_TKILL, -1, 3 }, -#endif - { SI_QUEUE, -1, 4 }, - { SI_MESGQ, -1, 5 }, - { CLD_EXITED, SIGCHLD, 6 }, - { CLD_KILLED, SIGCHLD, 7 }, - { CLD_DUMPED, SIGCHLD, 8 }, - { CLD_TRAPPED, SIGCHLD, 9 }, - { CLD_STOPPED, SIGCHLD, 10 }, - { CLD_CONTINUED, SIGCHLD, 11 }, -}; - -uint8_t sighook_signal_cause(const siginfo_t *info) { - const size_t const_len = sizeof consts / sizeof *consts; - size_t i; - for (i = 0; i < const_len; i ++) { - if ( - consts[i].native == info->si_code && - (consts[i].signal == -1 || consts[i].signal == info->si_signo) - ) { - return consts[i].translated; - } - } - return 0; // The "Unknown" variant -} - -pid_t sighook_signal_pid(const siginfo_t *info) { - return info->si_pid; -} - -uid_t sighook_signal_uid(const siginfo_t *info) { - return info->si_uid; -} diff --git a/vendor/signal-hook/src/low_level/mod.rs b/vendor/signal-hook/src/low_level/mod.rs deleted file mode 100644 index bf99fac78..000000000 --- a/vendor/signal-hook/src/low_level/mod.rs +++ /dev/null @@ -1,59 +0,0 @@ -//! Some low level utilities -//! -//! More often to build other abstractions than used directly. - -use std::io::Error; - -use libc::c_int; - -#[cfg(feature = "channel")] -#[cfg_attr(docsrs, doc(cfg(feature = "channel")))] -pub mod channel; -#[cfg(not(windows))] -#[cfg_attr(docsrs, doc(cfg(not(windows))))] -pub mod pipe; -#[cfg(feature = "extended-siginfo-raw")] -#[cfg_attr(docsrs, doc(cfg(feature = "extended-siginfo-raw")))] -pub mod siginfo; -mod signal_details; - -pub use signal_hook_registry::{register, unregister}; - -pub use self::signal_details::{emulate_default_handler, signal_name}; - -/// The usual raise, just the safe wrapper around it. -/// -/// This is async-signal-safe. -pub fn raise(sig: c_int) -> Result<(), Error> { - let result = unsafe { libc::raise(sig) }; - if result == -1 { - Err(Error::last_os_error()) - } else { - Ok(()) - } -} - -/// A bare libc abort. -/// -/// Unlike the [std::process::abort], this one is guaranteed to contain no additions or wrappers -/// and therefore is async-signal-safe. You can use this to terminate the application from within a -/// signal handler. -pub fn abort() -> ! { - unsafe { - libc::abort(); - } -} - -/// A bare libc exit. -/// -/// Unlike the [std::process::exit], this one is guaranteed to contain no additions or wrappers and -/// therefore is async-signal-safe. You can use this to terminate the application from within a -/// signal handler. -/// -/// Also, see [`register_conditional_shutdown`][crate::flag::register_conditional_shutdown]. -pub fn exit(status: c_int) -> ! { - unsafe { - // Yes, the one with underscore. That one doesn't call the at-exit hooks. - libc::_exit(status); - } -} diff --git a/vendor/signal-hook/src/low_level/pipe.rs b/vendor/signal-hook/src/low_level/pipe.rs deleted file mode 100644 index 3cd218743..000000000 --- a/vendor/signal-hook/src/low_level/pipe.rs +++ /dev/null @@ -1,265 +0,0 @@ -//! Module with the self-pipe pattern. -//! -//! One of the common patterns around signals is to have a pipe with both ends in the same program. -//! Whenever there's a signal, the signal handler writes one byte of garbage data to the write end, -//! unless the pipe's already full. The application then can handle the read end. -//! -//! This has two advantages. First, the real signal action moves outside of the signal handler -//! where there are a lot less restrictions. Second, it fits nicely in all kinds of asynchronous -//! loops and has less chance of race conditions. -//! -//! This module offers premade functions for the write end (and doesn't insist that it must be a -//! pipe ‒ anything that can be written to is fine ‒ sockets too, therefore `UnixStream::pair` is a -//! good candidate). -//! -//! If you want to integrate with some asynchronous library, plugging streams from `mio-uds` or -//! `tokio-uds` libraries should work. -//! -//! If it looks too low-level for your needs, the [`iterator`][crate::iterator] module contains some -//! higher-lever interface that also uses a self-pipe pattern under the hood. -//! -//! # Correct order of handling -//! -//! A care needs to be taken to avoid race conditions, especially when handling the same signal in -//! a loop. Specifically, another signal might come when the action for the previous signal is -//! being taken. The correct order is first to clear the content of the pipe (read some/all data -//! from it) and then take the action. This way a spurious wakeup can happen (the pipe could wake -//! up even when no signal came after the signal was taken, because ‒ it arrived between cleaning -//! the pipe and taking the action). Note that some OS primitives (eg. `select`) suffer from -//! spurious wakeups themselves (they can claim a FD is readable when it is not true) and blocking -//! `read` might return prematurely (with eg. `EINTR`). -//! -//! The reverse order of first taking the action and then clearing the pipe might lose signals, -//! which is usually worse. -//! -//! This is not a problem with blocking on reading from the pipe (because both the blocking and -//! cleaning is the same action), but in case of asynchronous handling it matters. -//! -//! If you want to combine setting some flags with a self-pipe pattern, the flag needs to be set -//! first, then the pipe written. On the read end, first the pipe needs to be cleaned, then the -//! flag and then the action taken. This is what the [`SignalsInfo`][crate::iterator::SignalsInfo] -//! structure does internally. -//! -//! # Write collating -//! -//! While unlikely if handled correctly, it is possible the write end is full when a signal comes. -//! In such case the signal handler simply does nothing. If the write end is full, the read end is -//! readable and therefore will wake up. On the other hand, blocking in the signal handler would -//! definitely be a bad idea. -//! -//! However, this also means the number of bytes read from the end might be lower than the number -//! of signals that arrived. This should not generally be a problem, since the OS already collates -//! signals of the same kind together. -//! -//! # Examples -//! -//! This example waits for at last one `SIGUSR1` signal to come before continuing (and -//! terminating). It sends the signal to itself, so it correctly terminates. -//! -//! ```rust -//! use std::io::{Error, Read}; -//! use std::os::unix::net::UnixStream; -//! -//! use signal_hook::consts::SIGUSR1; -//! use signal_hook::low_level::{pipe, raise}; -//! -//! fn main() -> Result<(), Error> { -//! let (mut read, write) = UnixStream::pair()?; -//! pipe::register(SIGUSR1, write)?; -//! // This will write into the pipe write end through the signal handler -//! raise(SIGUSR1).unwrap(); -//! let mut buff = [0]; -//! read.read_exact(&mut buff)?; -//! println!("Happily terminating"); -//! Ok(()) -//! } - -use std::io::{Error, ErrorKind}; -use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd}; - -use libc::{self, c_int}; - -use crate::SigId; - -#[cfg(target_os = "aix")] -const MSG_NOWAIT: i32 = libc::MSG_NONBLOCK; -#[cfg(not(target_os = "aix"))] -const MSG_NOWAIT: i32 = libc::MSG_DONTWAIT; - -#[derive(Copy, Clone)] -pub(crate) enum WakeMethod { - Send, - Write, -} - -struct WakeFd { - fd: RawFd, - method: WakeMethod, -} - -impl WakeFd { - /// Sets close on exec and nonblock on the inner file descriptor. - fn set_flags(&self) -> Result<(), Error> { - unsafe { - let flags = libc::fcntl(self.as_raw_fd(), libc::F_GETFL, 0); - if flags == -1 { - return Err(Error::last_os_error()); - } - let flags = flags | libc::O_NONBLOCK | libc::O_CLOEXEC; - if libc::fcntl(self.as_raw_fd(), libc::F_SETFL, flags) == -1 { - return Err(Error::last_os_error()); - } - } - Ok(()) - } - fn wake(&self) { - wake(self.fd, self.method); - } -} - -impl AsRawFd for WakeFd { - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -impl Drop for WakeFd { - fn drop(&mut self) { - unsafe { - libc::close(self.fd); - } - } -} - -pub(crate) fn wake(pipe: RawFd, method: WakeMethod) { - unsafe { - // This writes some data into the pipe. - // - // There are two tricks: - // * First, the crazy cast. The first part turns reference into pointer. The second part - // turns pointer to u8 into a pointer to void, which is what write requires. - // * Second, we ignore errors, on purpose. We don't have any means to handling them. The - // two conceivable errors are EBADFD, if someone passes a non-existent file descriptor or - // if it is closed. The second is EAGAIN, in which case the pipe is full ‒ there were - // many signals, but the reader didn't have time to read the data yet. It'll still get - // woken up, so not fitting another letter in it is fine. - let data = b"X" as *const _ as *const _; - match method { - WakeMethod::Write => libc::write(pipe, data, 1), - WakeMethod::Send => libc::send(pipe, data, 1, MSG_NOWAIT), - }; - } -} - -/// Registers a write to a self-pipe whenever there's the signal. -/// -/// In this case, the pipe is taken as the `RawFd`. It'll be closed on deregistration. Effectively, -/// the function takes ownership of the file descriptor. This includes feeling free to set arbitrary -/// flags on it, including file status flags (that are shared across file descriptors created by -/// `dup`). -/// -/// Note that passing the wrong file descriptor won't cause UB, but can still lead to severe bugs ‒ -/// like data corruptions in files. Prefer using [`register`] if possible. -/// -/// Also, it is perfectly legal for multiple writes to be collated together (if not consumed) and -/// to generate spurious wakeups (but will not generate spurious *bytes* in the pipe). -/// -/// # Internal details -/// -/// Internally, it *currently* does following. Note that this is *not* part of the stability -/// guarantees and may change if necessary. -/// -/// * If the file descriptor can be used with [`send`][libc::send], it'll be used together with -/// [`MSG_DONTWAIT`][libc::MSG_DONTWAIT]. This is tested by sending `0` bytes of data (depending -/// on the socket type, this might wake the read end with an empty message). -/// * If it is not possible, the [`O_NONBLOCK`][libc::O_NONBLOCK] will be set on the file -/// descriptor and [`write`][libc::write] will be used instead. -pub fn register_raw(signal: c_int, pipe: RawFd) -> Result<SigId, Error> { - let res = unsafe { libc::send(pipe, &[] as *const _, 0, MSG_NOWAIT) }; - let fd = match (res, Error::last_os_error().kind()) { - (0, _) | (-1, ErrorKind::WouldBlock) => WakeFd { - fd: pipe, - method: WakeMethod::Send, - }, - _ => { - let fd = WakeFd { - fd: pipe, - method: WakeMethod::Write, - }; - fd.set_flags()?; - fd - } - }; - let action = move || fd.wake(); - unsafe { super::register(signal, action) } -} - -/// Registers a write to a self-pipe whenever there's the signal. -/// -/// The ownership of pipe is taken and will be closed whenever the created action is unregistered. -/// -/// Note that if you want to register the same pipe for multiple signals, there's `try_clone` -/// method on many unix socket primitives. -/// -/// See [`register_raw`] for further details. -pub fn register<P>(signal: c_int, pipe: P) -> Result<SigId, Error> -where - P: IntoRawFd + 'static, -{ - register_raw(signal, pipe.into_raw_fd()) -} - -#[cfg(test)] -mod tests { - use std::io::Read; - use std::os::unix::net::{UnixDatagram, UnixStream}; - - use super::*; - - // Note: multiple tests share the SIGUSR1 signal. This is fine, we only need to know the signal - // arrives. It's OK to arrive multiple times, from multiple tests. - fn wakeup() { - crate::low_level::raise(libc::SIGUSR1).unwrap(); - } - - #[test] - fn register_with_socket() -> Result<(), Error> { - let (mut read, write) = UnixStream::pair()?; - register(libc::SIGUSR1, write)?; - wakeup(); - let mut buff = [0; 1]; - read.read_exact(&mut buff)?; - assert_eq!(b"X", &buff); - Ok(()) - } - - #[test] - #[cfg(not(target_os = "haiku"))] - fn register_dgram_socket() -> Result<(), Error> { - let (read, write) = UnixDatagram::pair()?; - register(libc::SIGUSR1, write)?; - wakeup(); - let mut buff = [0; 1]; - // The attempt to detect if it is socket can generate an empty message. Therefore, do a few - // retries. - for _ in 0..3 { - let len = read.recv(&mut buff)?; - if len == 1 && &buff == b"X" { - return Ok(()); - } - } - panic!("Haven't received the right data"); - } - - #[test] - fn register_with_pipe() -> Result<(), Error> { - let mut fds = [0; 2]; - unsafe { assert_eq!(0, libc::pipe(fds.as_mut_ptr())) }; - register_raw(libc::SIGUSR1, fds[1])?; - wakeup(); - let mut buff = [0; 1]; - unsafe { assert_eq!(1, libc::read(fds[0], buff.as_mut_ptr() as *mut _, 1)) } - assert_eq!(b"X", &buff); - Ok(()) - } -} diff --git a/vendor/signal-hook/src/low_level/siginfo.rs b/vendor/signal-hook/src/low_level/siginfo.rs deleted file mode 100644 index 9114d7f79..000000000 --- a/vendor/signal-hook/src/low_level/siginfo.rs +++ /dev/null @@ -1,261 +0,0 @@ -//! Extracting more information from the C [`siginfo_t`] structure. -//! -//! See [`Origin`]. - -use std::fmt::{Debug, Formatter, Result as FmtResult}; - -use libc::{c_int, pid_t, siginfo_t, uid_t}; - -use crate::low_level; - -// Careful: make sure the signature and the constants match the C source -extern "C" { - fn sighook_signal_cause(info: &siginfo_t) -> ICause; - fn sighook_signal_pid(info: &siginfo_t) -> pid_t; - fn sighook_signal_uid(info: &siginfo_t) -> uid_t; -} - -// Warning: must be in sync with the C code -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[non_exhaustive] -#[repr(u8)] -// For some reason, the fact it comes from the C makes rustc emit warning that *some* of these are -// not constructed. No idea why only some of them. -#[allow(dead_code)] -enum ICause { - Unknown = 0, - Kernel = 1, - User = 2, - TKill = 3, - Queue = 4, - MesgQ = 5, - Exited = 6, - Killed = 7, - Dumped = 8, - Trapped = 9, - Stopped = 10, - Continued = 11, -} - -impl ICause { - // The MacOs doesn't use the SI_* constants and leaves si_code at 0. But it doesn't use an - // union, it has a good-behaved struct with fields and therefore we *can* read the values, - // even though they'd contain nonsense (zeroes). We wipe that out later. - #[cfg(target_os = "macos")] - fn has_process(self) -> bool { - true - } - - #[cfg(not(target_os = "macos"))] - fn has_process(self) -> bool { - use ICause::*; - match self { - Unknown | Kernel => false, - User | TKill | Queue | MesgQ | Exited | Killed | Dumped | Trapped | Stopped - | Continued => true, - } - } -} - -/// Information about process, as presented in the signal metadata. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub struct Process { - /// The process ID. - pub pid: pid_t, - - /// The user owning the process. - pub uid: uid_t, -} - -impl Process { - /** - * Extract the process information. - * - * # Safety - * - * The `info` must have a `si_code` corresponding to some situation that has the `si_pid` - * and `si_uid` filled in. - */ - unsafe fn extract(info: &siginfo_t) -> Self { - Self { - pid: sighook_signal_pid(info), - uid: sighook_signal_uid(info), - } - } -} - -/// The means by which a signal was sent by other process. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub enum Sent { - /// The `kill` call. - User, - - /// The `tkill` call. - /// - /// This is likely linux specific. - TKill, - - /// `sigqueue`. - Queue, - - /// `mq_notify`. - MesgQ, -} - -/// A child changed its state. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub enum Chld { - /// The child exited normally. - Exited, - - /// It got killed by a signal. - Killed, - - /// It got killed by a signal and dumped core. - Dumped, - - /// The child was trapped by a `SIGTRAP` signal. - Trapped, - - /// The child got stopped. - Stopped, - - /// The child continued (after being stopped). - Continued, -} - -/// What caused a signal. -/// -/// This is a best-effort (and possibly incomplete) representation of the C `siginfo_t::si_code`. -/// It may differ between OSes and may be extended in future versions. -/// -/// Note that this doesn't contain all the „fault“ signals (`SIGILL`, `SIGSEGV` and similar). -/// There's no reasonable way to use the exfiltrators with them, since the handler either needs to -/// terminate the process or somehow recover from the situation. Things based on exfiltrators do -/// neither, which would cause an UB and therefore these values just don't make sense. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[non_exhaustive] -pub enum Cause { - /// The cause is unknown. - /// - /// Some systems don't fill this in. Some systems have values we don't understand. Some signals - /// don't have specific reasons to come to being. - Unknown, - - /// Sent by the kernel. - /// - /// This probably exists only on Linux. - Kernel, - - /// The signal was sent by other process. - Sent(Sent), - - /// A `SIGCHLD`, caused by a child process changing state. - Chld(Chld), -} - -impl From<ICause> for Cause { - fn from(c: ICause) -> Cause { - match c { - ICause::Kernel => Cause::Kernel, - ICause::User => Cause::Sent(Sent::User), - ICause::TKill => Cause::Sent(Sent::TKill), - ICause::Queue => Cause::Sent(Sent::Queue), - ICause::MesgQ => Cause::Sent(Sent::MesgQ), - ICause::Exited => Cause::Chld(Chld::Exited), - ICause::Killed => Cause::Chld(Chld::Killed), - ICause::Dumped => Cause::Chld(Chld::Dumped), - ICause::Trapped => Cause::Chld(Chld::Trapped), - ICause::Stopped => Cause::Chld(Chld::Stopped), - ICause::Continued => Cause::Chld(Chld::Continued), - // Unknown and possibly others if the underlying lib is updated - _ => Cause::Unknown, - } - } -} - -/// Information about a signal and its origin. -/// -/// This is produced by the [`WithOrigin`] exfiltrator (or can be [extracted][Origin::extract] from -/// `siginfo_t` by hand). -#[derive(Clone, Eq, PartialEq)] -#[non_exhaustive] -pub struct Origin { - /// The signal that happened. - pub signal: c_int, - - /// Information about the process that caused the signal. - /// - /// Note that not all signals are caused by a specific process or have the information - /// available („fault“ signals like `SIGBUS` don't have, any signal may be sent by the kernel - /// instead of a specific process). - /// - /// This is filled in whenever available. For most signals, this is the process that sent the - /// signal (by `kill` or similar), for `SIGCHLD` it is the child that caused the signal. - pub process: Option<Process>, - - /// How the signal happened. - /// - /// This is a best-effort value. In particular, some systems may have causes not known to this - /// library. Some other systems (MacOS) does not fill the value in so there's no way to know. - /// In all these cases, this will contain [`Cause::Unknown`]. - /// - /// Some values are platform specific and not available on other systems. - /// - /// Future versions may enrich the enum by further values. - pub cause: Cause, -} - -impl Debug for Origin { - fn fmt(&self, fmt: &mut Formatter) -> FmtResult { - fn named_signal(sig: c_int) -> String { - low_level::signal_name(sig) - .map(|n| format!("{} ({})", n, sig)) - .unwrap_or_else(|| sig.to_string()) - } - fmt.debug_struct("Origin") - .field("signal", &named_signal(self.signal)) - .field("process", &self.process) - .field("cause", &self.cause) - .finish() - } -} - -impl Origin { - /// Extracts the Origin from a raw `siginfo_t` structure. - /// - /// This function is async-signal-safe, can be called inside a signal handler. - /// - /// # Safety - /// - /// On systems where the structure is backed by an union on the C side, this requires the - /// `si_code` and `si_signo` fields must be set properly according to what fields are - /// available. - /// - /// The value passed by kernel satisfies this, care must be taken only when constructed - /// manually. - pub unsafe fn extract(info: &siginfo_t) -> Self { - let cause = sighook_signal_cause(info); - let process = if cause.has_process() { - let process = Process::extract(info); - // On macos we don't have the si_code to go by, but we can go by the values being - // empty there. - if cfg!(target_os = "macos") && process.pid == 0 && process.uid == 0 { - None - } else { - Some(process) - } - } else { - None - }; - let signal = info.si_signo; - Origin { - cause: cause.into(), - signal, - process, - } - } -} diff --git a/vendor/signal-hook/src/low_level/signal_details.rs b/vendor/signal-hook/src/low_level/signal_details.rs deleted file mode 100644 index 303f4e422..000000000 --- a/vendor/signal-hook/src/low_level/signal_details.rs +++ /dev/null @@ -1,255 +0,0 @@ -//! Providing auxiliary information for signals. - -use std::io::Error; -use std::mem; -use std::ptr; - -use libc::{c_int, EINVAL}; -#[cfg(not(windows))] -use libc::{sigset_t, SIG_UNBLOCK}; - -use crate::consts::signal::*; -use crate::low_level; - -#[derive(Clone, Copy, Debug)] -enum DefaultKind { - Ignore, - #[cfg(not(windows))] - Stop, - Term, -} - -struct Details { - signal: c_int, - name: &'static str, - default_kind: DefaultKind, -} - -macro_rules! s { - ($name: expr, $kind: ident) => { - Details { - signal: $name, - name: stringify!($name), - default_kind: DefaultKind::$kind, - } - }; -} - -#[cfg(not(windows))] -const DETAILS: &[Details] = &[ - s!(SIGABRT, Term), - s!(SIGALRM, Term), - s!(SIGBUS, Term), - s!(SIGCHLD, Ignore), - // Technically, continue the process... but this is not done *by* the process. - s!(SIGCONT, Ignore), - s!(SIGFPE, Term), - s!(SIGHUP, Term), - s!(SIGILL, Term), - s!(SIGINT, Term), - #[cfg(any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "netbsd", - target_os = "openbsd", - target_os = "macos" - ))] - s!(SIGINFO, Ignore), - #[cfg(not(target_os = "haiku"))] - s!(SIGIO, Ignore), - // Can't override anyway, but... - s!(SIGKILL, Term), - s!(SIGPIPE, Term), - s!(SIGPROF, Term), - s!(SIGQUIT, Term), - s!(SIGSEGV, Term), - // Can't override anyway, but... - s!(SIGSTOP, Stop), - s!(SIGSYS, Term), - s!(SIGTERM, Term), - s!(SIGTRAP, Term), - s!(SIGTSTP, Stop), - s!(SIGTTIN, Stop), - s!(SIGTTOU, Stop), - s!(SIGURG, Ignore), - s!(SIGUSR1, Term), - s!(SIGUSR2, Term), - s!(SIGVTALRM, Term), - s!(SIGWINCH, Ignore), - s!(SIGXCPU, Term), - s!(SIGXFSZ, Term), -]; - -#[cfg(windows)] -const DETAILS: &[Details] = &[ - s!(SIGABRT, Term), - s!(SIGFPE, Term), - s!(SIGILL, Term), - s!(SIGINT, Term), - s!(SIGSEGV, Term), - s!(SIGTERM, Term), -]; - -/// Provides a human-readable name of a signal. -/// -/// Note that the name does not have to be known (in case it is some less common, or non-standard -/// signal). -/// -/// # Examples -/// -/// ``` -/// # use signal_hook::low_level::signal_name; -/// assert_eq!("SIGKILL", signal_name(9).unwrap()); -/// assert!(signal_name(142).is_none()); -/// ``` -pub fn signal_name(signal: c_int) -> Option<&'static str> { - DETAILS.iter().find(|d| d.signal == signal).map(|d| d.name) -} - -#[cfg(not(windows))] -fn restore_default(signal: c_int) -> Result<(), Error> { - unsafe { - // A C structure, supposed to be memset to 0 before use. - let mut action: libc::sigaction = mem::zeroed(); - #[cfg(target_os = "aix")] - { - action.sa_union.__su_sigaction = mem::transmute::< - usize, - extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void), - >(libc::SIG_DFL); - } - #[cfg(not(target_os = "aix"))] - { action.sa_sigaction = libc::SIG_DFL as _; } - if libc::sigaction(signal, &action, ptr::null_mut()) == 0 { - Ok(()) - } else { - Err(Error::last_os_error()) - } - } -} - -#[cfg(windows)] -fn restore_default(signal: c_int) -> Result<(), Error> { - unsafe { - // SIG_DFL = 0, but not in libc :-( - if libc::signal(signal, 0) == 0 { - Ok(()) - } else { - Err(Error::last_os_error()) - } - } -} - -/// Emulates the behaviour of a default handler for the provided signal. -/// -/// This function does its best to provide the same action as the default handler would do, without -/// disrupting the rest of the handling of such signal in the application. It is also -/// async-signal-safe. -/// -/// This function necessarily looks up the appropriate action in a table. That means it is possible -/// your system has a signal that is not known to this function. In such case an error is returned -/// (equivalent of `EINVAL`). -/// -/// See also the [`register_conditional_default`][crate::flag::register_conditional_default]. -/// -/// # Warning -/// -/// There's a short race condition in case of signals that terminate (either with or without a core -/// dump). The emulation first resets the signal handler back to default (as the application is -/// going to end, it's not a problem) and invokes it. But if some other thread installs a signal -/// handler in the meantime (without assistance from `signal-hook`), it can happen this will be -/// invoked by the re-raised signal. -/// -/// This function will still terminate the application (there's a fallback on `abort`), the risk is -/// invoking the newly installed signal handler. Note that manipulating the low-level signals is -/// always racy in a multi-threaded program, therefore the described situation is already -/// discouraged. -/// -/// If you are uneasy about such race condition, the recommendation is to run relevant termination -/// routine manually ([`exit`][super::exit] or [`abort`][super::abort]); they always do what they -/// say, but slightly differ in externally observable behaviour from termination by a signal (the -/// exit code will specify that the application exited, not that it terminated with a signal in the -/// first case, and `abort` terminates on `SIGABRT`, so the detected termination signal may be -/// different). -pub fn emulate_default_handler(signal: c_int) -> Result<(), Error> { - #[cfg(not(windows))] - { - if signal == SIGSTOP || signal == SIGKILL { - return low_level::raise(signal); - } - } - let kind = DETAILS - .iter() - .find(|d| d.signal == signal) - .map(|d| d.default_kind) - .ok_or_else(|| Error::from_raw_os_error(EINVAL))?; - match kind { - DefaultKind::Ignore => Ok(()), - #[cfg(not(windows))] - DefaultKind::Stop => low_level::raise(SIGSTOP), - DefaultKind::Term => { - if let Ok(()) = restore_default(signal) { - #[cfg(not(windows))] - unsafe { - #[allow(deprecated)] - let mut newsigs: sigset_t = mem::zeroed(); - - // Some android versions don't have the sigemptyset and sigaddset. - // Unfortunately, we don't have an access to the android _version_. We just - // know that 64bit versions are all OK, so this is a best-effort guess. - // - // For the affected/guessed versions, we provide our own implementation. We - // hope it to be correct (it's inspired by a libc implementation and we assume - // the kernel uses the same format ‒ it's unlikely to be different both because - // of compatibility and because there's really nothing to invent about a - // bitarray). - // - // We use the proper way for other systems. - #[cfg(all(target_os = "android", target_pointer_width = "32"))] - unsafe fn prepare_sigset(set: *mut sigset_t, mut signal: c_int) { - signal -= 1; - let set_raw: *mut libc::c_ulong = set.cast(); - let size = mem::size_of::<libc::c_ulong>(); - assert_eq!(set_raw as usize % mem::align_of::<libc::c_ulong>(), 0); - let pos = signal as usize / size; - assert!(pos < mem::size_of::<sigset_t>() / size); - let bit = 1 << (signal as usize % size); - set_raw.add(pos).write(bit); - } - - #[cfg(not(all(target_os = "android", target_pointer_width = "32")))] - unsafe fn prepare_sigset(set: *mut sigset_t, signal: c_int) { - libc::sigemptyset(set); - libc::sigaddset(set, signal); - } - - prepare_sigset(&mut newsigs, signal); - // Ignore the result, if it doesn't work, we try anyway - // Also, sigprocmask is unspecified, but available on more systems. And we want - // to just enable _something_. And if it doesn't work, we'll terminate - // anyway... It's not UB, so we are good. - libc::sigprocmask(SIG_UNBLOCK, &newsigs, ptr::null_mut()); - } - let _ = low_level::raise(signal); - } - // Fallback if anything failed or someone managed to put some other action in in - // between. - unsafe { libc::abort() } - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn existing() { - assert_eq!("SIGTERM", signal_name(SIGTERM).unwrap()); - } - - #[test] - fn unknown() { - assert!(signal_name(128).is_none()); - } -} diff --git a/vendor/signal-hook/tests/default.rs b/vendor/signal-hook/tests/default.rs deleted file mode 100644 index bccf55891..000000000 --- a/vendor/signal-hook/tests/default.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Check the hack of SIG_DFL for windows. -//! -//! Libc doesn't export SIG_DFL on windows. It seems to be 0 on all platforms, though, but just to -//! make sure, we observe it is so. We try to read the previous signal on startup and it must be -//! the default. - -extern crate libc; - -use libc::{sighandler_t, signal, SIGTERM}; - -const SIG_DFL: sighandler_t = 0; - -#[test] -fn sig_dfl() { - unsafe { - let prev = signal(SIGTERM, SIG_DFL); - assert_eq!(SIG_DFL, prev); - } -} - -#[cfg(not(windows))] -#[test] -fn sig_dfl_static() { - assert_eq!(::libc::SIG_DFL, SIG_DFL); -} diff --git a/vendor/signal-hook/tests/iterator.rs b/vendor/signal-hook/tests/iterator.rs deleted file mode 100644 index 90e0598fe..000000000 --- a/vendor/signal-hook/tests/iterator.rs +++ /dev/null @@ -1,260 +0,0 @@ -#![cfg(not(windows))] - -extern crate signal_hook; - -use std::collections::HashSet; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::mpsc::{self, RecvTimeoutError}; -use std::sync::Arc; -use std::thread::{self, JoinHandle}; -use std::time::Duration; - -use signal_hook::consts::{SIGUSR1, SIGUSR2}; -use signal_hook::iterator::{Handle, Signals}; -use signal_hook::low_level::raise; - -use serial_test::serial; - -fn send_sigusr1() { - raise(SIGUSR1).unwrap(); -} - -fn send_sigusr2() { - raise(SIGUSR2).unwrap(); -} - -fn setup_without_any_signals() -> (Signals, Handle) { - let signals = Signals::new(&[]).unwrap(); - let controller = signals.handle(); - (signals, controller) -} - -fn setup_for_sigusr2() -> (Signals, Handle) { - let signals = Signals::new(&[SIGUSR2]).unwrap(); - let controller = signals.handle(); - (signals, controller) -} - -macro_rules! assert_signals { - ($actual:expr, $($expected:expr),+ $(,)?) => { - let actual = $actual.collect::<HashSet<libc::c_int>>(); - let expected = vec!($($expected),+).into_iter().collect::<HashSet<libc::c_int>>(); - assert_eq!(actual, expected); - }; -} - -macro_rules! assert_no_signals { - ($signals:expr) => { - assert_eq!($signals.next(), None); - }; -} - -#[test] -#[serial] -fn forever_terminates_when_closed() { - let (mut signals, controller) = setup_for_sigusr2(); - - // Detect early terminations. - let stopped = Arc::new(AtomicBool::new(false)); - - let stopped_bg = Arc::clone(&stopped); - let thread = thread::spawn(move || { - // Eat all the signals there are (might come from a concurrent test, in theory). - // Would wait forever, but it should be terminated by the close below. - for _sig in &mut signals {} - - stopped_bg.store(true, Ordering::SeqCst); - }); - - // Wait a bit to see if the thread terminates by itself. - thread::sleep(Duration::from_millis(100)); - assert!(!stopped.load(Ordering::SeqCst)); - - controller.close(); - - thread.join().unwrap(); -} - -// A reproducer for #16: if we had the mio-support enabled (which is enabled also by the -// tokio-support feature), blocking no longer works. The .wait() would return immediately (an empty -// iterator, possibly), .forever() would do a busy loop. -// flag) -#[test] -#[serial] -fn signals_block_wait() { - let mut signals = Signals::new(&[SIGUSR2]).unwrap(); - let (s, r) = mpsc::channel(); - let finish = Arc::new(AtomicBool::new(false)); - let thread_id = thread::spawn({ - let finish = Arc::clone(&finish); - move || { - // Technically, it may spuriously return early. But it shouldn't be doing it too much, - // so we just try to wait multiple times ‒ if they *all* return right away, it is - // broken. - for _ in 0..10 { - for _ in signals.wait() { - if finish.load(Ordering::SeqCst) { - // Asked to terminate at the end of the thread. Do so (but without - // signalling the receipt). - return; - } else { - panic!("Someone really did send us SIGUSR2, which breaks the test"); - } - } - } - let _ = s.send(()); - } - }); - - // A RAII guard to make sure we shut down the thread even if the test fails. - struct ThreadGuard { - thread: Option<JoinHandle<()>>, - finish: Arc<AtomicBool>, - } - - impl ThreadGuard { - fn shutdown(&mut self) { - // Tell it to shut down - self.finish.store(true, Ordering::SeqCst); - // Wake it up - send_sigusr2(); - // Wait for it to actually terminate. - if let Some(thread) = self.thread.take() { - thread.join().unwrap(); // Propagate panics - } - } - } - - impl Drop for ThreadGuard { - fn drop(&mut self) { - self.shutdown(); // OK if done twice, won't have the thread any more. - } - } - - let mut bg_thread = ThreadGuard { - thread: Some(thread_id), - finish, - }; - - let err = r - .recv_timeout(Duration::from_millis(100)) - .expect_err("Wait didn't wait properly"); - assert_eq!(err, RecvTimeoutError::Timeout); - - bg_thread.shutdown(); -} - -#[test] -#[serial] -fn pending_doesnt_block() { - let (mut signals, _) = setup_for_sigusr2(); - - let mut recieved_signals = signals.pending(); - - assert_no_signals!(recieved_signals); -} - -#[test] -#[serial] -fn wait_returns_recieved_signals() { - let (mut signals, _) = setup_for_sigusr2(); - send_sigusr2(); - - let recieved_signals = signals.wait(); - - assert_signals!(recieved_signals, SIGUSR2); -} - -#[test] -#[serial] -fn forever_returns_recieved_signals() { - let (mut signals, _) = setup_for_sigusr2(); - send_sigusr2(); - - let signal = signals.forever().take(1); - - assert_signals!(signal, SIGUSR2); -} - -#[test] -#[serial] -fn wait_doesnt_block_when_closed() { - let (mut signals, controller) = setup_for_sigusr2(); - controller.close(); - - let mut recieved_signals = signals.wait(); - - assert_no_signals!(recieved_signals); -} - -#[test] -#[serial] -fn wait_unblocks_when_closed() { - let (mut signals, controller) = setup_without_any_signals(); - - let thread = thread::spawn(move || { - signals.wait(); - }); - - controller.close(); - - thread.join().unwrap(); -} - -#[test] -#[serial] -fn forever_doesnt_block_when_closed() { - let (mut signals, controller) = setup_for_sigusr2(); - controller.close(); - - let mut signal = signals.forever(); - - assert_no_signals!(signal); -} - -#[test] -#[serial] -fn add_signal_after_creation() { - let (mut signals, _) = setup_without_any_signals(); - signals.add_signal(SIGUSR1).unwrap(); - - send_sigusr1(); - - assert_signals!(signals.pending(), SIGUSR1); -} - -#[test] -#[serial] -fn delayed_signal_consumed() { - let (mut signals, _) = setup_for_sigusr2(); - signals.add_signal(SIGUSR1).unwrap(); - - send_sigusr1(); - let mut recieved_signals = signals.wait(); - send_sigusr2(); - - assert_signals!(recieved_signals, SIGUSR1, SIGUSR2); - - // The pipe still contains the byte from the second - // signal and so wait won't block but won't return - // a signal. - recieved_signals = signals.wait(); - assert_no_signals!(recieved_signals); -} - -#[test] -#[serial] -fn is_closed_initially_returns_false() { - let (_, controller) = setup_for_sigusr2(); - - assert!(!controller.is_closed()); -} - -#[test] -#[serial] -fn is_closed_returns_true_when_closed() { - let (_, controller) = setup_for_sigusr2(); - controller.close(); - - assert!(controller.is_closed()); -} diff --git a/vendor/signal-hook/tests/shutdown.rs b/vendor/signal-hook/tests/shutdown.rs deleted file mode 100644 index 381fab729..000000000 --- a/vendor/signal-hook/tests/shutdown.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Tests for the shutdown. -//! -//! The tests work like this: -//! -//! * The register an alarm, to fail if anything takes too long (which is very much possible here). -//! * A fork is done, with the child registering a signal with a NOP and cleanup operation (one or -//! the other). -//! * The child puts some kind of infinite loop or sleep inside itself, so it never actually -//! terminates on the first, but would terminate after the signal. - -#![cfg(not(windows))] // Forks don't work on Windows, but windows has the same implementation. - -use std::io::Error; -use std::ptr; -use std::sync::atomic::AtomicBool; -use std::sync::Arc; -use std::thread; -use std::time::Duration; - -use signal_hook::consts::signal::*; -use signal_hook::flag; -use signal_hook::low_level; - -fn do_test<C: FnOnce()>(child: C) { - unsafe { - libc::alarm(10); // Time out the test after 10 seconds and get it killed. - match libc::fork() { - -1 => panic!("Fork failed: {}", Error::last_os_error()), - 0 => { - child(); - loop { - thread::sleep(Duration::from_secs(1)); - } - } - pid => { - // Give the child some time to register signals and stuff - // We could actually signal that the child is ready by it eg. closing STDOUT, but - // this is just a test so we don't really bother. - thread::sleep(Duration::from_millis(250)); - libc::kill(pid, libc::SIGTERM); - // Wait a small bit to make sure the signal got delivered. - thread::sleep(Duration::from_millis(50)); - // The child is still running, because the first signal got "handled" by being - // ignored. - let terminated = libc::waitpid(pid, ptr::null_mut(), libc::WNOHANG); - assert_eq!(0, terminated, "Process {} terminated prematurely", pid); - // But it terminates on the second attempt (we do block on wait here). - libc::kill(pid, libc::SIGTERM); - let terminated = libc::waitpid(pid, ptr::null_mut(), 0); - assert_eq!(pid, terminated); - } - } - } -} - -/// Use automatic cleanup inside the signal handler to get rid of old signals, the aggressive way. -#[test] -fn cleanup_inside_signal() { - fn hook() { - // Make sure we have some signal handler, not the default. - unsafe { low_level::register(SIGTERM, || ()).unwrap() }; - let shutdown_cond = Arc::new(AtomicBool::new(false)); - // „disarmed“ shutdown - flag::register_conditional_shutdown(SIGTERM, 0, Arc::clone(&shutdown_cond)).unwrap(); - // But arm at the first SIGTERM - flag::register(SIGTERM, shutdown_cond).unwrap(); - } - do_test(hook); -} - -/// Manually remove the signal handler just after receiving the signal but before going into an -/// infinite loop. -#[test] -fn cleanup_after_signal() { - fn hook() { - let mut signals = signal_hook::iterator::Signals::new(&[libc::SIGTERM]).unwrap(); - assert_eq!(Some(SIGTERM), signals.into_iter().next()); - flag::register_conditional_shutdown(SIGTERM, 0, Arc::new(AtomicBool::new(true))).unwrap(); - } - do_test(hook); -} |