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