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 #![warn(missing_docs)]
15
16 //! # ylong_signal
17 //! Provides methods to set or unset an action for signal handler.
18
19 mod common;
20 pub use common::SIGNAL_BLOCK_LIST;
21
22 mod sig_map;
23 mod spin_rwlock;
24 #[cfg(windows)]
25 mod windows;
26
27 #[cfg(not(windows))]
28 mod unix;
29
30 use std::io;
31
32 use libc::c_int;
33
34 /// Registers a user-defined function for the signal action.
35 ///
36 /// Currently this function only supports registering one action for each
37 /// signal. If another component in the process sets a signal action
38 /// without using this method, this old action will be overwritten by the
39 /// new registered action. After unregistering this old action will
40 /// in turn overwrite the new registered ation.
41 /// # Errors
42 ///
43 /// Calling this fuction twice on the same signal without a call to
44 /// [`deregister_signal_action`] will result in an `AlreadyExists` error.
45 ///
46 /// Calling this function on the following signal will result in a
47 /// `InvalidInput` error:
48 /// - `SIGSEGV`
49 /// - `SIGKILL`
50 /// - `SIGSTOP`
51 /// - `SIGFPE`
52 /// - `SIGILL`
53 /// This function doesn't support setting actions for these signals due to POSIX
54 /// settings or their needs of special handling.
55 ///
56 /// # Safety
57 ///
58 /// This function is unsafe, because it sets a function to be run in a signal
59 /// handler as there are a lot of limitations (async-signal-safe) on what you
60 /// can do inside a signal handler. For example, you should not use blocking
61 /// Mutex since it could cause the program become deadlocked.
62 ///
63 /// # Example
64 /// ```no run
65 /// let res = unsafe {
66 /// ylong_signal::register_signal_action(libc::SIGTERM, move || {
67 /// println!("inside SIGTERM signal handler");
68 /// })
69 /// };
70 /// assert!(res.is_ok());
71 /// ```
register_signal_action<F>(sig_num: c_int, handler: F) -> io::Result<()> where F: Fn() + Sync + Send + 'static,72 pub unsafe fn register_signal_action<F>(sig_num: c_int, handler: F) -> io::Result<()>
73 where
74 F: Fn() + Sync + Send + 'static,
75 {
76 common::Signal::register_action(sig_num, move |_| handler())
77 }
78
79 /// Deregisters the signal action set to a specific signal by a previous call to
80 /// [`register_signal_action`].
81 ///
82 /// If the signal passed in has not been set before by
83 /// [`register_signal_action`], this function will do nothing.
84 ///
85 /// If the signal passed in has been set before by [`register_signal_action`],
86 /// then the action of the signal will be dropped, and the overwritten old
87 /// action will take its place. The overwrite action may fail and return an
88 /// error.
89 ///
90 /// After calling this function, you could call [`register_signal_action`] again
91 /// on the same signal.
92 ///
93 /// # Example
94 /// ```no run
95 /// ylong_signal::deregister_signal_action(libc::SIGTERM);
96 /// ```
deregister_signal_action(sig_num: c_int) -> io::Result<()>97 pub fn deregister_signal_action(sig_num: c_int) -> io::Result<()> {
98 common::Signal::deregister_action(sig_num)
99 }
100
101 /// Deregisters the signal handler of a signal along with all its previous
102 /// registered actions.
103 ///
104 /// The remove of the signal handler will influence all components inside the
105 /// process, therefore you should be cautious when calling this function.
106 ///
107 /// # Example
108 /// ```no run
109 /// let res = ylong_signal::deregister_signal_hook(libc::SIGTERM);
110 /// assert!(res.is_ok());
111 /// ```
deregister_signal_hook(sig_num: c_int) -> io::Result<()>112 pub fn deregister_signal_hook(sig_num: c_int) -> io::Result<()> {
113 common::Signal::deregister_hook(sig_num)
114 }
115