1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //! Asynchronous signal handling. 15 16 #[cfg(unix)] 17 pub mod unix; 18 #[cfg(unix)] 19 pub use unix::{signal, SignalKind}; 20 21 #[cfg(target_os = "windows")] 22 pub mod windows; 23 use std::task::{Context, Poll}; 24 25 #[cfg(target_os = "windows")] 26 pub use windows::{signal, SignalKind}; 27 28 use crate::sync::watch::Receiver; 29 30 /// A listener for monitoring operating system signals. 31 /// 32 /// # Unix 33 /// This listener will merge signals of the same kind and receive them in a 34 /// stream, so for multiple triggers of the same signal, the receiver may only 35 /// receive one notification, which includes all triggered signal kinds. 36 /// 37 /// When registering a listener for a certain kind of signal for the first time, 38 /// it will replace the default platform processing behavior. If some process 39 /// termination signals are triggered, the process will not be terminated 40 /// immediately, but will merge the signals into the stream and trigger them 41 /// uniformly, which will be captured and processed by the corresponding 42 /// receiver. Deconstructing the receiver does not reset the default platform 43 /// processing behavior. 44 /// 45 /// # Examples 46 /// On Windows system 47 /// 48 /// ```no run 49 /// use ylong_runtime::signal::{signal, SignalKind}; 50 /// async fn io_func() { 51 /// let handle = ylong_runtime::spawn(async move { 52 /// let mut signal = signal(SignalKind::ctrl_c()).unwrap(); 53 /// signal.recv().await; 54 /// }); 55 /// let _ = ylong_runtime::block_on(handle); 56 /// } 57 /// ``` 58 /// 59 /// On Unix system 60 /// 61 /// ```no run 62 /// use ylong_runtime::signal::{signal, SignalKind}; 63 /// async fn io_func() { 64 /// let handle = ylong_runtime::spawn(async move { 65 /// let mut signal = signal(SignalKind::child()).unwrap(); 66 /// signal.recv().await; 67 /// }); 68 /// let _ = ylong_runtime::block_on(handle); 69 /// } 70 /// ``` 71 pub struct Signal { 72 inner: Receiver<()>, 73 } 74 75 impl Signal { 76 /// Waits for signal notification. 77 /// 78 /// # Examples 79 /// On Windows system 80 /// 81 /// ```no run 82 /// use ylong_runtime::signal::{signal, SignalKind}; 83 /// async fn io_func() { 84 /// let handle = ylong_runtime::spawn(async move { 85 /// let mut signal = signal(SignalKind::ctrl_c()).unwrap(); 86 /// signal.recv().await; 87 /// }); 88 /// let _ = ylong_runtime::block_on(handle); 89 /// } 90 /// ``` 91 /// 92 /// On Unix system 93 /// 94 /// ```no run 95 /// use ylong_runtime::signal::{signal, SignalKind}; 96 /// async fn io_func() { 97 /// let handle = ylong_runtime::spawn(async move { 98 /// let mut signal = signal(SignalKind::child()).unwrap(); 99 /// signal.recv().await; 100 /// }); 101 /// let _ = ylong_runtime::block_on(handle); 102 /// } 103 /// ``` recv(&mut self)104 pub async fn recv(&mut self) { 105 // The sender is saved in the registry of the global singleton and should not be 106 // deconstructed. 107 self.inner 108 .notified() 109 .await 110 .unwrap_or_else(|e| panic!("Signal sender has been dropped, error: {e}")); 111 } 112 113 /// Polls to waits for signal notification. 114 /// 115 /// # Return value 116 /// * `Poll::Pending` if no notification comes. 117 /// * `Poll::Ready(())` if receiving a new signal notification. 118 /// 119 /// # Examples 120 /// On Windows system 121 /// 122 /// ```no run 123 /// use ylong_runtime::futures::poll_fn; 124 /// use ylong_runtime::signal::{signal, SignalKind}; 125 /// async fn io_func() { 126 /// let handle = ylong_runtime::spawn(async move { 127 /// let mut signal = signal(SignalKind::ctrl_c()).unwrap(); 128 /// poll_fn(|cx| signal.poll_recv(cx)).await; 129 /// }); 130 /// let _ = ylong_runtime::block_on(handle); 131 /// } 132 /// ``` 133 /// 134 /// On Unix system 135 /// 136 /// ```no run 137 /// use ylong_runtime::futures::poll_fn; 138 /// use ylong_runtime::signal::{signal, SignalKind}; 139 /// async fn io_func() { 140 /// let handle = ylong_runtime::spawn(async move { 141 /// let mut signal = signal(SignalKind::child()).unwrap(); 142 /// poll_fn(|cx| signal.poll_recv(cx)).await; 143 /// }); 144 /// let _ = ylong_runtime::block_on(handle); 145 /// } 146 /// ``` poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<()>147 pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<()> { 148 // The sender is saved in the registry of the global singleton and should not be 149 // deconstructed. 150 match self.inner.poll_notified(cx) { 151 Poll::Ready(Ok(())) => Poll::Ready(()), 152 Poll::Ready(Err(_)) => panic!("Signal sender has been dropped"), 153 Poll::Pending => Poll::Pending, 154 } 155 } 156 } 157