diff --git a/Cargo.lock b/Cargo.lock index 2bed6b022c09..8f122ac1a2f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4761,15 +4761,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - [[package]] name = "siphasher" version = "0.3.10" @@ -5273,10 +5264,7 @@ dependencies = [ "memchr", "mio 0.8.0", "num_cpus", - "once_cell", - "parking_lot 0.12.999", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", "winapi", diff --git a/netwerk/test/http3server/Cargo.toml b/netwerk/test/http3server/Cargo.toml index 5094eaff1415..fca4f9e79fe5 100644 --- a/netwerk/test/http3server/Cargo.toml +++ b/netwerk/test/http3server/Cargo.toml @@ -17,7 +17,7 @@ base64 = "0.21" cfg-if = "1.0" http = "0.2.8" hyper = { version = "0.14", features = ["full"] } -tokio = { version = "1", features = ["full"] } +tokio = { version = "1", features = ["rt-multi-thread"] } [dependencies.neqo-crypto] tag = "v0.6.4" diff --git a/supply-chain/config.toml b/supply-chain/config.toml index b21798d7d9a7..fd9498b68f17 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -789,10 +789,6 @@ criteria = "safe-to-deploy" version = "1.1.0" criteria = "safe-to-deploy" -[[exemptions.signal-hook-registry]] -version = "1.4.1" -criteria = "safe-to-run" - [[exemptions.siphasher]] version = "0.3.10" criteria = "safe-to-deploy" diff --git a/third_party/rust/cose/.cargo-checksum.json b/third_party/rust/cose/.cargo-checksum.json index 8c50fccfb3bf..851cac0db602 100644 --- a/third_party/rust/cose/.cargo-checksum.json +++ b/third_party/rust/cose/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"e4af309a907a63866cc85b7e8d878d083790ef9b5733a5129906eb26eedfd80c","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"981c13c037304ca06c34d8518f2d2e0021867dfd36cb711efb8f6c5e2fdb0123","build.rs":"a2b798bbeaf8ef19a9bd8c1e24b3fd3899a5b4b3e121e5e09794e4e2b35971dd","examples/sign_verify/main.rs":"fbe4b9c73b23e1ef364126f453f749fefb67ab45703bf809a5eed910a25e461e","examples/sign_verify/nss.rs":"a1d133142efc0ac6564f0b9587890587f1ecaa7404ac0c4c8907de6d43de3267","examples/sign_verify/test_nss.rs":"be41ebe0a82b6172297b10c13767e4768f0b613ac331b554f6e8c2c7a20c0bc8","examples/sign_verify/test_setup.rs":"d323c3818525a43b71c3a121b39043c5debdff303fa3cfec230853c96ff477eb","examples/sign_verify/util_test.rs":"48d52f3ca3e93b670a1d69f8443358260c1ae61d7977a59d922696811320d4c3","rustfmt.toml":"e97717e906fcd3eeb86dcee52ed26f13e1884597b016a27172229d9c78dd3d57","src/cose.rs":"104e06843f4cdffe2ca6f42f46c51c79d685c18d2ad92b65811e3ceffbd90e07","src/decoder.rs":"d84fc785715823963551466175af0bb86a16cee58ae95b54bfd613d390bc4d82","src/test_cose.rs":"849ec936a00eb438a08eb85380b3e4ba8d8c5a5cf674b272e0fd8e671ab6d5ca","src/test_setup.rs":"e26f290831343cbb4e2b2ec7d1be34c7b900eb8c87abd6f40629372a87b6e992","src/util.rs":"8cdcdc8a120e71a772af61fa63ffa2d2d2eb572d8a53da3b5f1ce9da784f2662","tools/certs/certs.md":"7a1acd946f5bb5b9b21ebd7653ef9d5746a1ea237131a69218a91dc26eda545a","tools/certs/certs.sh":"a06e1a7bf99316c7800e388d20c1630da7449937635600d9f21d8d93907011bf","tools/certs/ee-p256.certspec":"5a7246c0abf1ee08edb858ce2fd38010de7785a0e8652f2d9a0b7eee7aa39213","tools/certs/ee-p256.keyspec":"eabd2839f9e57cf2c372e686e5856cf651d7f07d0d396b3699d1d228b5931945","tools/certs/ee-p384.certspec":"d2e4fdd6d8f02f22bffa800ac2b7f899f5d826528e7b7d3248e1abea15cd33bd","tools/certs/ee-p521.certspec":"7ad1fc3cdf024dfa7213f3a2875af0ccfa2bd73fddcfaf73223aa25b24ee2cad","tools/certs/ee-rsa.certspec":"dd69ecbb1cdf322fb8ef6eb50c2f033b62e7983b5448b96f1965eee8f85b7bde","tools/certs/int-p256.certspec":"b42a2286339455626b9a8b6c0811b031bf269440c6fcef7478796d02c5491364","tools/certs/int-rsa.certspec":"a0942438c72a3ce83b54c04e4a5d4bff08036c2c9feb7d75a7105bfa4fdc5499","tools/certs/root-p256.certspec":"99c1bb07505ddfc3ada5737d8a1bf4cff7b1a70a79abda9fd45fc3a6e72061fc","tools/certs/root-rsa.certspec":"67903313b6058aa98be0d98564577b0c878c868b6f2a8758f27bb7af17616d8e"},"package":null} +{"files":{".travis.yml":"423ecb6dd6dbc8b00fb3d2789ddc89ab4d9c1040ea3d5e467f437728164cd5b9","Cargo.toml":"e4af309a907a63866cc85b7e8d878d083790ef9b5733a5129906eb26eedfd80c","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"981c13c037304ca06c34d8518f2d2e0021867dfd36cb711efb8f6c5e2fdb0123","build.rs":"a2b798bbeaf8ef19a9bd8c1e24b3fd3899a5b4b3e121e5e09794e4e2b35971dd","examples/sign_verify/main.rs":"fbe4b9c73b23e1ef364126f453f749fefb67ab45703bf809a5eed910a25e461e","examples/sign_verify/nss.rs":"a1d133142efc0ac6564f0b9587890587f1ecaa7404ac0c4c8907de6d43de3267","examples/sign_verify/test_nss.rs":"be41ebe0a82b6172297b10c13767e4768f0b613ac331b554f6e8c2c7a20c0bc8","examples/sign_verify/test_setup.rs":"d323c3818525a43b71c3a121b39043c5debdff303fa3cfec230853c96ff477eb","examples/sign_verify/util_test.rs":"48d52f3ca3e93b670a1d69f8443358260c1ae61d7977a59d922696811320d4c3","rustfmt.toml":"e97717e906fcd3eeb86dcee52ed26f13e1884597b016a27172229d9c78dd3d57","src/cose.rs":"104e06843f4cdffe2ca6f42f46c51c79d685c18d2ad92b65811e3ceffbd90e07","src/decoder.rs":"d84fc785715823963551466175af0bb86a16cee58ae95b54bfd613d390bc4d82","src/test_cose.rs":"849ec936a00eb438a08eb85380b3e4ba8d8c5a5cf674b272e0fd8e671ab6d5ca","src/test_setup.rs":"e26f290831343cbb4e2b2ec7d1be34c7b900eb8c87abd6f40629372a87b6e992","src/util.rs":"8cdcdc8a120e71a772af61fa63ffa2d2d2eb572d8a53da3b5f1ce9da784f2662","tools/certs/certs.md":"7a1acd946f5bb5b9b21ebd7653ef9d5746a1ea237131a69218a91dc26eda545a","tools/certs/certs.sh":"a06e1a7bf99316c7800e388d20c1630da7449937635600d9f21d8d93907011bf","tools/certs/ee-p256.certspec":"5a7246c0abf1ee08edb858ce2fd38010de7785a0e8652f2d9a0b7eee7aa39213","tools/certs/ee-p256.keyspec":"eabd2839f9e57cf2c372e686e5856cf651d7f07d0d396b3699d1d228b5931945","tools/certs/ee-p384.certspec":"d2e4fdd6d8f02f22bffa800ac2b7f899f5d826528e7b7d3248e1abea15cd33bd","tools/certs/ee-p521.certspec":"7ad1fc3cdf024dfa7213f3a2875af0ccfa2bd73fddcfaf73223aa25b24ee2cad","tools/certs/ee-rsa.certspec":"dd69ecbb1cdf322fb8ef6eb50c2f033b62e7983b5448b96f1965eee8f85b7bde","tools/certs/int-p256.certspec":"b42a2286339455626b9a8b6c0811b031bf269440c6fcef7478796d02c5491364","tools/certs/int-rsa.certspec":"a0942438c72a3ce83b54c04e4a5d4bff08036c2c9feb7d75a7105bfa4fdc5499","tools/certs/root-p256.certspec":"99c1bb07505ddfc3ada5737d8a1bf4cff7b1a70a79abda9fd45fc3a6e72061fc","tools/certs/root-rsa.certspec":"67903313b6058aa98be0d98564577b0c878c868b6f2a8758f27bb7af17616d8e"},"package":null} \ No newline at end of file diff --git a/third_party/rust/cose/.travis.yml b/third_party/rust/cose/.travis.yml new file mode 100644 index 000000000000..f0fbb9cbeece --- /dev/null +++ b/third_party/rust/cose/.travis.yml @@ -0,0 +1,28 @@ +dist: bionic +language: rust +cache: cargo +os: + - linux +rust: + - stable + - beta + - nightly + +addons: + apt: + packages: + - build-essential + - libnss3-dev + +#install: +# Apparently cargo install returns a nonzero exit status if +# caching succeeds, so just make this always "succeed". +# - (cargo install rustfmt --force || true) + +script: +#- | +# cargo fmt -- --write-mode=diff +- | + cargo build --features "$FEATURES" && + cargo test && + cargo run --example sign_verify diff --git a/third_party/rust/signal-hook-registry/.cargo-checksum.json b/third_party/rust/signal-hook-registry/.cargo-checksum.json deleted file mode 100644 index f09d3b006913..000000000000 --- a/third_party/rust/signal-hook-registry/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"42fe4108f3d88108c7d65d951a56842f47644a8a4e2d6932c34b9a9fae098316","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"503558bfefe66ca15e4e3f7955b3cb0ec87fd52f29bf24b336af7bd00e946d5c","README.md":"56d8abee3efdf82aed1791a81feb60d9db987cedfa9c2e2a6b9451ac94bb88f7","src/half_lock.rs":"548fc2e283ef638a9f90e194d112a11c94205c87004d6da2e65eaa98f7a5a670","src/lib.rs":"1ed9cb19bfcde72036f983e2800ffa10c7ef4df0a0500bc697c49374260f1ac8","tests/unregister_signal.rs":"5baeebbde2bd7e63ae9a1f1e476d33f0bfd368c1edcdab3677de6a62b04f5118"},"package":"d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"} \ No newline at end of file diff --git a/third_party/rust/signal-hook-registry/Cargo.toml b/third_party/rust/signal-hook-registry/Cargo.toml deleted file mode 100644 index 064358fbc8c1..000000000000 --- a/third_party/rust/signal-hook-registry/Cargo.toml +++ /dev/null @@ -1,40 +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] -name = "signal-hook-registry" -version = "1.4.1" -authors = [ - "Michal 'vorner' Vaner ", - "Masaki Hara ", -] -description = "Backend crate for signal-hook" -documentation = "https://docs.rs/signal-hook-registry" -readme = "README.md" -keywords = [ - "signal", - "unix", - "daemon", -] -license = "Apache-2.0/MIT" -repository = "https://github.com/vorner/signal-hook" - -[dependencies.libc] -version = "~0.2" - -[dev-dependencies.signal-hook] -version = "~0.3" - -[badges.maintenance] -status = "actively-developed" - -[badges.travis-ci] -repository = "vorner/signal-hook" diff --git a/third_party/rust/signal-hook-registry/LICENSE-APACHE b/third_party/rust/signal-hook-registry/LICENSE-APACHE deleted file mode 100644 index 16fe87b06e80..000000000000 --- a/third_party/rust/signal-hook-registry/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/third_party/rust/signal-hook-registry/LICENSE-MIT b/third_party/rust/signal-hook-registry/LICENSE-MIT deleted file mode 100644 index ebe0bc91ea70..000000000000 --- a/third_party/rust/signal-hook-registry/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/third_party/rust/signal-hook-registry/README.md b/third_party/rust/signal-hook-registry/README.md deleted file mode 100644 index eb4773328f35..000000000000 --- a/third_party/rust/signal-hook-registry/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Signal-hook-registry - -[![Travis Build Status](https://api.travis-ci.org/vorner/signal-hook.svg?branch=master)](https://travis-ci.org/vorner/signal-hook) - -This is the backend crate for the -[signal-hook](https://crates.io/crates/signal-hook) crate. The general direct use of -this crate is discouraged. See the -[documentation](https://docs.rs/signal-hook-registry) for further details. - -## 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/third_party/rust/signal-hook-registry/src/half_lock.rs b/third_party/rust/signal-hook-registry/src/half_lock.rs deleted file mode 100644 index 61d858cf4f51..000000000000 --- a/third_party/rust/signal-hook-registry/src/half_lock.rs +++ /dev/null @@ -1,232 +0,0 @@ -//! The half-lock structure -//! -//! We need a way to protect the structure with configured hooks ‒ a signal may happen in arbitrary -//! thread and needs to read them while another thread might be manipulating the structure. -//! -//! Under ordinary circumstances we would be happy to just use `Mutex>`. However, -//! as we use it in the signal handler, we are severely limited in what we can or can't use. So we -//! choose to implement kind of spin-look thing with atomics. -//! -//! In the reader it is always simply locked and then unlocked, making sure it doesn't disappear -//! while in use. -//! -//! The writer has a separate mutex (that prevents other writers; this is used outside of the -//! signal handler), makes a copy of the data and swaps an atomic pointer to the data structure. -//! But it waits until everything is unlocked (no signal handler has the old data) for dropping the -//! old instance. There's a generation trick to make sure that new signal locks another instance. -//! -//! The downside is, this is an active spin lock at the writer end. However, we assume than: -//! -//! * Signals are one time setup before we actually have threads. We just need to make *sure* we -//! are safe even if this is not true. -//! * Signals are rare, happening at the same time as the write even rarer. -//! * Signals are short, as there is mostly nothing allowed inside them anyway. -//! * Our tool box is severely limited. -//! -//! Therefore this is hopefully reasonable trade-off. -//! -//! # Atomic orderings -//! -//! The whole code uses SeqCst conservatively. Atomics are not used because of performance here and -//! are the minor price around signals anyway. But the comments state which orderings should be -//! enough in practice in case someone wants to get inspired (but do make your own check through -//! them anyway). - -use std::isize; -use std::marker::PhantomData; -use std::ops::Deref; -use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering}; -use std::sync::{Mutex, MutexGuard, PoisonError}; -use std::thread; - -use libc; - -const YIELD_EVERY: usize = 16; -const MAX_GUARDS: usize = (isize::MAX) as usize; - -pub(crate) struct ReadGuard<'a, T: 'a> { - data: &'a T, - lock: &'a AtomicUsize, -} - -impl<'a, T> Deref for ReadGuard<'a, T> { - type Target = T; - fn deref(&self) -> &T { - self.data - } -} - -impl<'a, T> Drop for ReadGuard<'a, T> { - fn drop(&mut self) { - // We effectively unlock; Release would be enough. - self.lock.fetch_sub(1, Ordering::SeqCst); - } -} - -pub(crate) struct WriteGuard<'a, T: 'a> { - _guard: MutexGuard<'a, ()>, - lock: &'a HalfLock, - data: &'a T, -} - -impl<'a, T> WriteGuard<'a, T> { - pub(crate) fn store(&mut self, val: T) { - // Move to the heap and convert to raw pointer for AtomicPtr. - let new = Box::into_raw(Box::new(val)); - - self.data = unsafe { &*new }; - - // We can just put the new value in here safely, we worry only about dropping the old one. - // Release might (?) be enough, to "upload" the data. - let old = self.lock.data.swap(new, Ordering::SeqCst); - - // Now we make sure there's no reader having the old data. - self.lock.write_barrier(); - - drop(unsafe { Box::from_raw(old) }); - } -} - -impl<'a, T> Deref for WriteGuard<'a, T> { - type Target = T; - fn deref(&self) -> &T { - // Protected by that mutex - self.data - } -} - -pub(crate) struct HalfLock { - // We conceptually contain an instance of T - _t: PhantomData, - // The actual data as a pointer. - data: AtomicPtr, - // The generation of the data. Influences which slot of the lock counter we use. - generation: AtomicUsize, - // How many active locks are there? - lock: [AtomicUsize; 2], - // Mutex for the writers; only one writer. - write_mutex: Mutex<()>, -} - -impl HalfLock { - pub(crate) fn new(data: T) -> Self { - // Move to the heap so we can safely point there. Then convert to raw pointer as AtomicPtr - // operates on raw pointers. The AtomicPtr effectively acts like Box for us semantically. - let ptr = Box::into_raw(Box::new(data)); - Self { - _t: PhantomData, - data: AtomicPtr::new(ptr), - generation: AtomicUsize::new(0), - lock: [AtomicUsize::new(0), AtomicUsize::new(0)], - write_mutex: Mutex::new(()), - } - } - - pub(crate) fn read(&self) -> ReadGuard { - // Relaxed should be enough; we only pick one or the other slot and the writer observes - // that both were 0 at some time. So the actual value doesn't really matter for safety, - // only the changing improves the performance. - let gen = self.generation.load(Ordering::SeqCst); - let lock = &self.lock[gen % 2]; - // Effectively locking something, acquire should be enough. - let guard_cnt = lock.fetch_add(1, Ordering::SeqCst); - - // This is to prevent overflowing the counter in some degenerate cases, which could lead to - // UB (freeing data while still in use). However, as this data structure is used only - // internally and it's not possible to leak the guard and the guard itself takes some - // memory, it should be really impossible to trigger this case. Still, we include it from - // abundance of caution. - // - // This technically is not fully correct as enough threads being in between here and the - // abort below could still overflow it and it could get freed for some *other* thread, but - // that would mean having too many active threads to fit into RAM too and is even more - // absurd corner case than the above. - if guard_cnt > MAX_GUARDS { - unsafe { libc::abort() }; - } - - // Acquire should be enough; we need to "download" the data, paired with the swap on the - // same pointer. - let data = self.data.load(Ordering::SeqCst); - // Safe: - // * It did point to valid data when put in. - // * Protected by lock, so still valid. - let data = unsafe { &*data }; - - ReadGuard { data, lock } - } - - fn update_seen(&self, seen_zero: &mut [bool; 2]) { - for (seen, slot) in seen_zero.iter_mut().zip(&self.lock) { - *seen = *seen || slot.load(Ordering::SeqCst) == 0; - } - } - - fn write_barrier(&self) { - // Do a first check of seeing zeroes before we switch the generation. At least one of them - // should be zero by now, due to having drained the generation before leaving the previous - // writer. - let mut seen_zero = [false; 2]; - self.update_seen(&mut seen_zero); - // By switching the generation to the other slot, we make sure the currently active starts - // draining while the other will start filling up. - self.generation.fetch_add(1, Ordering::SeqCst); // Overflow is fine. - - let mut iter = 0usize; - while !seen_zero.iter().all(|s| *s) { - iter = iter.wrapping_add(1); - - // Be somewhat less aggressive while looping, switch to the other threads if possible. - if cfg!(not(miri)) { - if iter % YIELD_EVERY == 0 { - thread::yield_now(); - } else { - // Replaced by hint::spin_loop, but we want to support older compiler - #[allow(deprecated)] - atomic::spin_loop_hint(); - } - } - - self.update_seen(&mut seen_zero); - } - } - - pub(crate) fn write(&self) -> WriteGuard { - // While it's possible the user code panics, our code in store doesn't and the data gets - // swapped atomically. So if it panics, nothing gets changed, therefore poisons are of no - // interest here. - let guard = self - .write_mutex - .lock() - .unwrap_or_else(PoisonError::into_inner); - - // Relaxed should be enough, as we are under the same mutex that was used to get the data - // in. - let data = self.data.load(Ordering::SeqCst); - // Safe: - // * Stored as valid data - // * Only this method, protected by mutex, can change the pointer, so it didn't go away. - let data = unsafe { &*data }; - - WriteGuard { - data, - _guard: guard, - lock: self, - } - } -} - -impl Drop for HalfLock { - fn drop(&mut self) { - // During drop we are sure there are no other borrows of the data so we are free to just - // drop it. Also, the drop impl won't be called in practice in our case, as it is used - // solely as a global variable, but we provide it for completeness and tests anyway. - // - // unsafe: the pointer in there is always valid, we just take the last instance out. - unsafe { - // Acquire should be enough. - let data = Box::from_raw(self.data.load(Ordering::SeqCst)); - drop(data); - } - } -} diff --git a/third_party/rust/signal-hook-registry/src/lib.rs b/third_party/rust/signal-hook-registry/src/lib.rs deleted file mode 100644 index e488906e649d..000000000000 --- a/third_party/rust/signal-hook-registry/src/lib.rs +++ /dev/null @@ -1,789 +0,0 @@ -#![doc(test(attr(deny(warnings))))] -#![warn(missing_docs)] -#![allow(unknown_lints, renamed_and_remove_lints, bare_trait_objects)] - -//! Backend of the [signal-hook] crate. -//! -//! The [signal-hook] crate tries to provide an API to the unix signals, which are a global -//! resource. Therefore, it is desirable an application contains just one version of the crate -//! which manages this global resource. But that makes it impossible to make breaking changes in -//! the API. -//! -//! Therefore, this crate provides very minimal and low level API to the signals that is unlikely -//! to have to change, while there may be multiple versions of the [signal-hook] that all use this -//! low-level API to provide different versions of the high level APIs. -//! -//! It is also possible some other crates might want to build a completely different API. This -//! split allows these crates to still reuse the same low-level routines in this crate instead of -//! going to the (much more dangerous) unix calls. -//! -//! # What this crate provides -//! -//! The only thing this crate does is multiplexing the signals. An application or library can add -//! or remove callbacks and have multiple callbacks for the same signal. -//! -//! It handles dispatching the callbacks and managing them in a way that uses only the -//! [async-signal-safe] functions inside the signal handler. Note that the callbacks are still run -//! inside the signal handler, so it is up to the caller to ensure they are also -//! [async-signal-safe]. -//! -//! # What this is for -//! -//! This is a building block for other libraries creating reasonable abstractions on top of -//! signals. The [signal-hook] is the generally preferred way if you need to handle signals in your -//! application and provides several safe patterns of doing so. -//! -//! # Rust version compatibility -//! -//! Currently builds on 1.26.0 an newer and this is very unlikely to change. However, tests -//! require dependencies that don't build there, so tests need newer Rust version (they are run on -//! stable). -//! -//! # Portability -//! -//! This crate includes a limited support for Windows, based on `signal`/`raise` in the CRT. -//! There are differences in both API and behavior: -//! -//! - Due to lack of `siginfo_t`, we don't provide `register_sigaction` or `register_unchecked`. -//! - 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. -//! -//! [signal-hook]: https://docs.rs/signal-hook -//! [async-signal-safe]: http://www.man7.org/linux/man-pages/man7/signal-safety.7.html - -extern crate libc; - -mod half_lock; - -use std::collections::hash_map::Entry; -use std::collections::{BTreeMap, HashMap}; -use std::io::Error; -use std::mem; -#[cfg(not(windows))] -use std::ptr; -// Once::new is now a const-fn. But it is not stable in all the rustc versions we want to support -// yet. -#[allow(deprecated)] -use std::sync::ONCE_INIT; -use std::sync::{Arc, Once}; - -#[cfg(not(windows))] -use libc::{c_int, c_void, sigaction, siginfo_t}; -#[cfg(windows)] -use libc::{c_int, sighandler_t}; - -#[cfg(not(windows))] -use libc::{SIGFPE, SIGILL, SIGKILL, SIGSEGV, SIGSTOP}; -#[cfg(windows)] -use libc::{SIGFPE, SIGILL, SIGSEGV}; - -use half_lock::HalfLock; - -// These constants are not defined in the current version of libc, but it actually -// exists in Windows CRT. -#[cfg(windows)] -const SIG_DFL: sighandler_t = 0; -#[cfg(windows)] -const SIG_IGN: sighandler_t = 1; -#[cfg(windows)] -const SIG_GET: sighandler_t = 2; -#[cfg(windows)] -const SIG_ERR: sighandler_t = !0; - -// To simplify implementation. Not to be exposed. -#[cfg(windows)] -#[allow(non_camel_case_types)] -struct siginfo_t; - -// # Internal workings -// -// This uses a form of RCU. There's an atomic pointer to the current action descriptors (in the -// form of IndependentArcSwap, to be able to track what, if any, signal handlers still use the -// version). A signal handler takes a copy of the pointer and calls all the relevant actions. -// -// Modifications to that are protected by a mutex, to avoid juggling multiple signal handlers at -// once (eg. not calling sigaction concurrently). This should not be a problem, because modifying -// the signal actions should be initialization only anyway. To avoid all allocations and also -// deallocations inside the signal handler, after replacing the pointer, the modification routine -// needs to busy-wait for the reference count on the old pointer to drop to 1 and take ownership ‒ -// that way the one deallocating is the modification routine, outside of the signal handler. - -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -struct ActionId(u128); - -/// An ID of registered action. -/// -/// This is returned by all the registration routines and can be used to remove the action later on -/// with a call to [`unregister`]. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct SigId { - signal: c_int, - action: ActionId, -} - -// This should be dyn Fn(...), but we want to support Rust 1.26.0 and that one doesn't allow dyn -// yet. -#[allow(unknown_lints, bare_trait_objects)] -type Action = Fn(&siginfo_t) + Send + Sync; - -#[derive(Clone)] -struct Slot { - prev: Prev, - // We use BTreeMap here, because we want to run the actions in the order they were inserted. - // This works, because the ActionIds are assigned in an increasing order. - actions: BTreeMap>, -} - -impl Slot { - #[cfg(windows)] - fn new(signal: libc::c_int) -> Result { - let old = unsafe { libc::signal(signal, handler as sighandler_t) }; - if old == SIG_ERR { - return Err(Error::last_os_error()); - } - Ok(Slot { - prev: Prev { signal, info: old }, - actions: BTreeMap::new(), - }) - } - - #[cfg(not(windows))] - fn new(signal: libc::c_int) -> Result { - // C data structure, expected to be zeroed out. - let mut new: libc::sigaction = unsafe { mem::zeroed() }; - #[cfg(not(target_os = "aix"))] - { new.sa_sigaction = handler as usize; } - #[cfg(target_os = "aix")] - { new.sa_union.__su_sigaction = handler; } - // Android is broken and uses different int types than the rest (and different depending on - // the pointer width). This converts the flags to the proper type no matter what it is on - // the given platform. - let flags = libc::SA_RESTART; - #[allow(unused_assignments)] - let mut siginfo = flags; - siginfo = libc::SA_SIGINFO as _; - let flags = flags | siginfo; - new.sa_flags = flags as _; - // C data structure, expected to be zeroed out. - let mut old: libc::sigaction = unsafe { mem::zeroed() }; - // FFI ‒ pointers are valid, it doesn't take ownership. - if unsafe { libc::sigaction(signal, &new, &mut old) } != 0 { - return Err(Error::last_os_error()); - } - Ok(Slot { - prev: Prev { signal, info: old }, - actions: BTreeMap::new(), - }) - } -} - -#[derive(Clone)] -struct SignalData { - signals: HashMap, - next_id: u128, -} - -#[derive(Clone)] -struct Prev { - signal: c_int, - #[cfg(windows)] - info: sighandler_t, - #[cfg(not(windows))] - info: sigaction, -} - -impl Prev { - #[cfg(windows)] - fn detect(signal: c_int) -> Result { - let old = unsafe { libc::signal(signal, SIG_GET) }; - if old == SIG_ERR { - return Err(Error::last_os_error()); - } - Ok(Prev { signal, info: old }) - } - - #[cfg(not(windows))] - fn detect(signal: c_int) -> Result { - // C data structure, expected to be zeroed out. - let mut old: libc::sigaction = unsafe { mem::zeroed() }; - // FFI ‒ pointers are valid, it doesn't take ownership. - if unsafe { libc::sigaction(signal, ptr::null(), &mut old) } != 0 { - return Err(Error::last_os_error()); - } - - Ok(Prev { signal, info: old }) - } - - #[cfg(windows)] - fn execute(&self, sig: c_int) { - let fptr = self.info; - if fptr != 0 && fptr != SIG_DFL && fptr != SIG_IGN { - // FFI ‒ calling the original signal handler. - unsafe { - let action = mem::transmute::(fptr); - action(sig); - } - } - } - - #[cfg(not(windows))] - unsafe fn execute(&self, sig: c_int, info: *mut siginfo_t, data: *mut c_void) { - #[cfg(not(target_os = "aix"))] - let fptr = self.info.sa_sigaction; - #[cfg(target_os = "aix")] - let fptr = self.info.sa_union.__su_sigaction as usize; - if fptr != 0 && fptr != libc::SIG_DFL && fptr != libc::SIG_IGN { - // Android is broken and uses different int types than the rest (and different - // depending on the pointer width). This converts the flags to the proper type no - // matter what it is on the given platform. - // - // The trick is to create the same-typed variable as the sa_flags first and then - // set it to the proper value (does Rust have a way to copy a type in a different - // way?) - #[allow(unused_assignments)] - let mut siginfo = self.info.sa_flags; - siginfo = libc::SA_SIGINFO as _; - if self.info.sa_flags & siginfo == 0 { - let action = mem::transmute::(fptr); - action(sig); - } else { - type SigAction = extern "C" fn(c_int, *mut siginfo_t, *mut c_void); - let action = mem::transmute::(fptr); - action(sig, info, data); - } - } - } -} - -/// Lazy-initiated data structure with our global variables. -/// -/// Used inside a structure to cut down on boilerplate code to lazy-initialize stuff. We don't dare -/// use anything fancy like lazy-static or once-cell, since we are not sure they are -/// async-signal-safe in their access. Our code uses the [Once], but only on the write end outside -/// of signal handler. The handler assumes it has already been initialized. -struct GlobalData { - /// The data structure describing what needs to be run for each signal. - data: HalfLock, - - /// A fallback to fight/minimize a race condition during signal initialization. - /// - /// See the comment inside [`register_unchecked_impl`]. - race_fallback: HalfLock>, -} - -static mut GLOBAL_DATA: Option = None; -#[allow(deprecated)] -static GLOBAL_INIT: Once = ONCE_INIT; - -impl GlobalData { - fn get() -> &'static Self { - unsafe { GLOBAL_DATA.as_ref().unwrap() } - } - fn ensure() -> &'static Self { - GLOBAL_INIT.call_once(|| unsafe { - GLOBAL_DATA = Some(GlobalData { - data: HalfLock::new(SignalData { - signals: HashMap::new(), - next_id: 1, - }), - race_fallback: HalfLock::new(None), - }); - }); - Self::get() - } -} - -#[cfg(windows)] -extern "C" fn handler(sig: c_int) { - if sig != SIGFPE { - // Windows CRT `signal` resets handler every time, unless for SIGFPE. - // Reregister the handler to retain maximal compatibility. - // Problems: - // - It's racy. But this is inevitably racy in Windows. - // - Interacts poorly with handlers outside signal-hook-registry. - let old = unsafe { libc::signal(sig, handler as sighandler_t) }; - if old == SIG_ERR { - // MSDN doesn't describe which errors might occur, - // but we can tell from the Linux manpage that - // EINVAL (invalid signal number) is mostly the only case. - // Therefore, this branch must not occur. - // In any case we can do nothing useful in the signal handler, - // so we're going to abort silently. - unsafe { - libc::abort(); - } - } - } - - let globals = GlobalData::get(); - let fallback = globals.race_fallback.read(); - let sigdata = globals.data.read(); - - if let Some(ref slot) = sigdata.signals.get(&sig) { - slot.prev.execute(sig); - - for action in slot.actions.values() { - action(&siginfo_t); - } - } else if let Some(prev) = fallback.as_ref() { - // In case we get called but don't have the slot for this signal set up yet, we are under - // the race condition. We may have the old signal handler stored in the fallback - // temporarily. - if sig == prev.signal { - prev.execute(sig); - } - // else -> probably should not happen, but races with other threads are possible so - // better safe - } -} - -#[cfg(not(windows))] -extern "C" fn handler(sig: c_int, info: *mut siginfo_t, data: *mut c_void) { - let globals = GlobalData::get(); - let fallback = globals.race_fallback.read(); - let sigdata = globals.data.read(); - - if let Some(slot) = sigdata.signals.get(&sig) { - unsafe { slot.prev.execute(sig, info, data) }; - - let info = unsafe { info.as_ref() }; - let info = info.unwrap_or_else(|| { - // The info being null seems to be illegal according to POSIX, but has been observed on - // some probably broken platform. We can't do anything about that, that is just broken, - // but we are not allowed to panic in a signal handler, so we are left only with simply - // aborting. We try to write a message what happens, but using the libc stuff - // (`eprintln` is not guaranteed to be async-signal-safe). - unsafe { - const MSG: &[u8] = - b"Platform broken, got NULL as siginfo to signal handler. Aborting"; - libc::write(2, MSG.as_ptr() as *const _, MSG.len()); - libc::abort(); - } - }); - - for action in slot.actions.values() { - action(info); - } - } else if let Some(prev) = fallback.as_ref() { - // In case we get called but don't have the slot for this signal set up yet, we are under - // the race condition. We may have the old signal handler stored in the fallback - // temporarily. - if prev.signal == sig { - unsafe { prev.execute(sig, info, data) }; - } - // else -> probably should not happen, but races with other threads are possible so - // better safe - } -} - -/// List of forbidden signals. -/// -/// Some signals are impossible to replace according to POSIX and some are so special that this -/// library refuses to handle them (eg. SIGSEGV). The routines panic in case registering one of -/// these signals is attempted. -/// -/// See [`register`]. -pub const FORBIDDEN: &[c_int] = FORBIDDEN_IMPL; - -#[cfg(windows)] -const FORBIDDEN_IMPL: &[c_int] = &[SIGILL, SIGFPE, SIGSEGV]; -#[cfg(not(windows))] -const FORBIDDEN_IMPL: &[c_int] = &[SIGKILL, SIGSTOP, SIGILL, SIGFPE, SIGSEGV]; - -/// Registers an arbitrary action for the given signal. -/// -/// This makes sure there's a signal handler for the given signal. It then adds the action to the -/// ones called each time the signal is delivered. If multiple actions are set for the same signal, -/// all are called, in the order of registration. -/// -/// If there was a previous signal handler for the given signal, it is chained ‒ it will be called -/// as part of this library's signal handler, before any actions set through this function. -/// -/// On success, the function returns an ID that can be used to remove the action again with -/// [`unregister`]. -/// -/// # Panics -/// -/// If the signal is one of (see [`FORBIDDEN`]): -/// -/// * `SIGKILL` -/// * `SIGSTOP` -/// * `SIGILL` -/// * `SIGFPE` -/// * `SIGSEGV` -/// -/// The first two are not possible to override (and the underlying C functions simply ignore all -/// requests to do so, which smells of possible bugs, or return errors). The rest can be set, but -/// generally needs very special handling to do so correctly (direct manipulation of the -/// application's address space, `longjmp` and similar). Unless you know very well what you're -/// doing, you'll shoot yourself into the foot and this library won't help you with that. -/// -/// # Errors -/// -/// Since the library manipulates signals using the low-level C functions, all these can return -/// errors. Generally, the errors mean something like the specified signal does not exist on the -/// given platform ‒ after a program is debugged and tested on a given OS, it should never return -/// an error. -/// -/// However, if an error *is* returned, there are no guarantees if the given action was registered -/// or not. -/// -/// # Safety -/// -/// This function is unsafe, because the `action` is run inside a signal handler. The set of -/// functions allowed to be called from within is very limited (they are called async-signal-safe -/// functions by POSIX). These specifically do *not* contain mutexes and memory -/// allocation/deallocation. They *do* contain routines to terminate the program, to further -/// manipulate signals (by the low-level functions, not by this library) and to read and write file -/// descriptors. Calling program's own functions consisting only of these is OK, as is manipulating -/// program's variables ‒ however, as the action can be called on any thread that does not have the -/// given signal masked (by default no signal is masked on any thread), and mutexes are a no-go, -/// this is harder than it looks like at first. -/// -/// As panicking from within a signal handler would be a panic across FFI boundary (which is -/// undefined behavior), the passed handler must not panic. -/// -/// If you find these limitations hard to satisfy, choose from the helper functions in the -/// [signal-hook](https://docs.rs/signal-hook) crate ‒ these provide safe interface to use some -/// common signal handling patters. -/// -/// # Race condition -/// -/// Upon registering the first hook for a given signal into this library, there's a short race -/// condition under the following circumstances: -/// -/// * The program already has a signal handler installed for this particular signal (through some -/// other library, possibly). -/// * Concurrently, some other thread installs a different signal handler while it is being -/// installed by this library. -/// * At the same time, the signal is delivered. -/// -/// Under such conditions signal-hook might wrongly "chain" to the older signal handler for a short -/// while (until the registration is fully complete). -/// -/// Note that the exact conditions of the race condition might change in future versions of the -/// library. The recommended way to avoid it is to register signals before starting any additional -/// threads, or at least not to register signals concurrently. -/// -/// Alternatively, make sure all signals are handled through this library. -/// -/// # Performance -/// -/// Even when it is possible to repeatedly install and remove actions during the lifetime of a -/// program, the installation and removal is considered a slow operation and should not be done -/// very often. Also, there's limited (though huge) amount of distinct IDs (they are `u128`). -/// -/// # Examples -/// -/// ```rust -/// extern crate signal_hook_registry; -/// -/// use std::io::Error; -/// use std::process; -/// -/// fn main() -> Result<(), Error> { -/// let signal = unsafe { -/// signal_hook_registry::register(signal_hook::consts::SIGTERM, || process::abort()) -/// }?; -/// // Stuff here... -/// signal_hook_registry::unregister(signal); // Not really necessary. -/// Ok(()) -/// } -/// ``` -pub unsafe fn register(signal: c_int, action: F) -> Result -where - F: Fn() + Sync + Send + 'static, -{ - register_sigaction_impl(signal, move |_: &_| action()) -} - -/// Register a signal action. -/// -/// This acts in the same way as [`register`], including the drawbacks, panics and performance -/// characteristics. The only difference is the provided action accepts a [`siginfo_t`] argument, -/// providing information about the received signal. -/// -/// # Safety -/// -/// See the details of [`register`]. -#[cfg(not(windows))] -pub unsafe fn register_sigaction(signal: c_int, action: F) -> Result -where - F: Fn(&siginfo_t) + Sync + Send + 'static, -{ - register_sigaction_impl(signal, action) -} - -unsafe fn register_sigaction_impl(signal: c_int, action: F) -> Result -where - F: Fn(&siginfo_t) + Sync + Send + 'static, -{ - assert!( - !FORBIDDEN.contains(&signal), - "Attempted to register forbidden signal {}", - signal, - ); - register_unchecked_impl(signal, action) -} - -/// Register a signal action without checking for forbidden signals. -/// -/// This acts in the same way as [`register_unchecked`], including the drawbacks, panics and -/// performance characteristics. The only difference is the provided action doesn't accept a -/// [`siginfo_t`] argument. -/// -/// # Safety -/// -/// See the details of [`register`]. -pub unsafe fn register_signal_unchecked(signal: c_int, action: F) -> Result -where - F: Fn() + Sync + Send + 'static, -{ - register_unchecked_impl(signal, move |_: &_| action()) -} - -/// Register a signal action without checking for forbidden signals. -/// -/// This acts the same way as [`register_sigaction`], but without checking for the [`FORBIDDEN`] -/// signals. All the signals passed are registered and it is up to the caller to make some sense of -/// them. -/// -/// Note that you really need to know what you're doing if you change eg. the `SIGSEGV` signal -/// handler. Generally, you don't want to do that. But unlike the other functions here, this -/// function still allows you to do it. -/// -/// # Safety -/// -/// See the details of [`register`]. -#[cfg(not(windows))] -pub unsafe fn register_unchecked(signal: c_int, action: F) -> Result -where - F: Fn(&siginfo_t) + Sync + Send + 'static, -{ - register_unchecked_impl(signal, action) -} - -unsafe fn register_unchecked_impl(signal: c_int, action: F) -> Result -where - F: Fn(&siginfo_t) + Sync + Send + 'static, -{ - let globals = GlobalData::ensure(); - let action = Arc::from(action); - - let mut lock = globals.data.write(); - - let mut sigdata = SignalData::clone(&lock); - let id = ActionId(sigdata.next_id); - sigdata.next_id += 1; - - match sigdata.signals.entry(signal) { - Entry::Occupied(mut occupied) => { - assert!(occupied.get_mut().actions.insert(id, action).is_none()); - } - Entry::Vacant(place) => { - // While the sigaction/signal exchanges the old one atomically, we are not able to - // atomically store it somewhere a signal handler could read it. That poses a race - // condition where we could lose some signals delivered in between changing it and - // storing it. - // - // Therefore we first store the old one in the fallback storage. The fallback only - // covers the cases where the slot is not yet active and becomes "inert" after that, - // even if not removed (it may get overwritten by some other signal, but for that the - // mutex in globals.data must be unlocked here - and by that time we already stored the - // slot. - // - // And yes, this still leaves a short race condition when some other thread could - // replace the signal handler and we would be calling the outdated one for a short - // time, until we install the slot. - globals - .race_fallback - .write() - .store(Some(Prev::detect(signal)?)); - - let mut slot = Slot::new(signal)?; - slot.actions.insert(id, action); - place.insert(slot); - } - } - - lock.store(sigdata); - - Ok(SigId { signal, action: id }) -} - -/// Removes a previously installed action. -/// -/// This function does nothing if the action was already removed. It returns true if it was removed -/// and false if the action wasn't found. -/// -/// It can unregister all the actions installed by [`register`] as well as the ones from downstream -/// crates (like [`signal-hook`](https://docs.rs/signal-hook)). -/// -/// # Warning -/// -/// This does *not* currently return the default/previous signal handler if the last action for a -/// signal was just unregistered. That means that if you replaced for example `SIGTERM` and then -/// removed the action, the program will effectively ignore `SIGTERM` signals from now on, not -/// terminate on them as is the default action. This is OK if you remove it as part of a shutdown, -/// but it is not recommended to remove termination actions during the normal runtime of -/// application (unless the desired effect is to create something that can be terminated only by -/// SIGKILL). -pub fn unregister(id: SigId) -> bool { - let globals = GlobalData::ensure(); - let mut replace = false; - let mut lock = globals.data.write(); - let mut sigdata = SignalData::clone(&lock); - if let Some(slot) = sigdata.signals.get_mut(&id.signal) { - replace = slot.actions.remove(&id.action).is_some(); - } - if replace { - lock.store(sigdata); - } - replace -} - -// We keep this one here for strict backwards compatibility, but the API is kind of bad. One can -// delete actions that don't belong to them, which is kind of against the whole idea of not -// breaking stuff for others. -#[deprecated( - since = "1.3.0", - note = "Don't use. Can influence unrelated parts of program / unknown actions" -)] -#[doc(hidden)] -pub fn unregister_signal(signal: c_int) -> bool { - let globals = GlobalData::ensure(); - let mut replace = false; - let mut lock = globals.data.write(); - let mut sigdata = SignalData::clone(&lock); - if let Some(slot) = sigdata.signals.get_mut(&signal) { - if !slot.actions.is_empty() { - slot.actions.clear(); - replace = true; - } - } - if replace { - lock.store(sigdata); - } - replace -} - -#[cfg(test)] -mod tests { - use std::sync::atomic::{AtomicUsize, Ordering}; - use std::sync::Arc; - use std::thread; - use std::time::Duration; - - #[cfg(not(windows))] - use libc::{pid_t, SIGUSR1, SIGUSR2}; - - #[cfg(windows)] - use libc::SIGTERM as SIGUSR1; - #[cfg(windows)] - use libc::SIGTERM as SIGUSR2; - - use super::*; - - #[test] - #[should_panic] - fn panic_forbidden() { - let _ = unsafe { register(SIGILL, || ()) }; - } - - /// Registering the forbidden signals is allowed in the _unchecked version. - #[test] - #[allow(clippy::redundant_closure)] // Clippy, you're wrong. Because it changes the return value. - fn forbidden_raw() { - unsafe { register_signal_unchecked(SIGFPE, || std::process::abort()).unwrap() }; - } - - #[test] - fn signal_without_pid() { - let status = Arc::new(AtomicUsize::new(0)); - let action = { - let status = Arc::clone(&status); - move || { - status.store(1, Ordering::Relaxed); - } - }; - unsafe { - register(SIGUSR2, action).unwrap(); - libc::raise(SIGUSR2); - } - for _ in 0..10 { - thread::sleep(Duration::from_millis(100)); - let current = status.load(Ordering::Relaxed); - match current { - // Not yet - 0 => continue, - // Good, we are done with the correct result - _ if current == 1 => return, - _ => panic!("Wrong result value {}", current), - } - } - panic!("Timed out waiting for the signal"); - } - - #[test] - #[cfg(not(windows))] - fn signal_with_pid() { - let status = Arc::new(AtomicUsize::new(0)); - let action = { - let status = Arc::clone(&status); - move |siginfo: &siginfo_t| { - // Hack: currently, libc exposes only the first 3 fields of siginfo_t. The pid - // comes somewhat later on. Therefore, we do a Really Ugly Hack and define our - // own structure (and hope it is correct on all platforms). But hey, this is - // only the tests, so we are going to get away with this. - #[repr(C)] - struct SigInfo { - _fields: [c_int; 3], - #[cfg(all(target_pointer_width = "64", target_os = "linux"))] - _pad: c_int, - pid: pid_t, - } - let s: &SigInfo = unsafe { - (siginfo as *const _ as usize as *const SigInfo) - .as_ref() - .unwrap() - }; - status.store(s.pid as usize, Ordering::Relaxed); - } - }; - let pid; - unsafe { - pid = libc::getpid(); - register_sigaction(SIGUSR2, action).unwrap(); - libc::raise(SIGUSR2); - } - for _ in 0..10 { - thread::sleep(Duration::from_millis(100)); - let current = status.load(Ordering::Relaxed); - match current { - // Not yet (PID == 0 doesn't happen) - 0 => continue, - // Good, we are done with the correct result - _ if current == pid as usize => return, - _ => panic!("Wrong status value {}", current), - } - } - panic!("Timed out waiting for the signal"); - } - - /// Check that registration works as expected and that unregister tells if it did or not. - #[test] - fn register_unregister() { - let signal = unsafe { register(SIGUSR1, || ()).unwrap() }; - // It was there now, so we can unregister - assert!(unregister(signal)); - // The next time unregistering does nothing and tells us so. - assert!(!unregister(signal)); - } -} diff --git a/third_party/rust/signal-hook-registry/tests/unregister_signal.rs b/third_party/rust/signal-hook-registry/tests/unregister_signal.rs deleted file mode 100644 index 6e13c0858487..000000000000 --- a/third_party/rust/signal-hook-registry/tests/unregister_signal.rs +++ /dev/null @@ -1,59 +0,0 @@ -//! Tests for the [unregister_signal] function. -//! -//! As a separate integration level test, so it doesn't clash with other tests on the signals. - -// The unregister_signal itself is deprecated. But we still want to test it, so it's not deprecated -// and broken at the same time. -#![allow(deprecated)] - -extern crate libc; -extern crate signal_hook_registry; - -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Arc; - -use libc::{SIGINT, SIGTERM}; // We'll use these here because SIGUSR1 is not available on Windows. -use signal_hook_registry::{register, unregister_signal}; - -#[test] -fn register_unregister() { - let called = Arc::new(AtomicUsize::new(0)); - - let hook = { - let called = Arc::clone(&called); - move || { - called.fetch_add(1, Ordering::Relaxed); - } - }; - - unsafe { - register(SIGTERM, hook.clone()).unwrap(); - register(SIGTERM, hook.clone()).unwrap(); - register(SIGINT, hook.clone()).unwrap(); - - libc::raise(SIGTERM); - } - - // The closure is run twice. - assert_eq!(2, called.load(Ordering::Relaxed)); - - assert!(unregister_signal(SIGTERM)); - - unsafe { libc::raise(SIGTERM) }; - // Second one unregisters nothing. - assert!(!unregister_signal(SIGTERM)); - - // After unregistering (both), it is no longer run at all. - assert_eq!(2, called.load(Ordering::Relaxed)); - - // The SIGINT one is not disturbed. - unsafe { libc::raise(SIGINT) }; - assert_eq!(3, called.load(Ordering::Relaxed)); - - // But it's possible to register it again just fine. - unsafe { - register(SIGTERM, hook).unwrap(); - libc::raise(SIGTERM); - } - assert_eq!(4, called.load(Ordering::Relaxed)); -}