• 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 use std::collections::HashMap;
15 use std::mem::MaybeUninit;
16 use std::sync::Once;
17 use std::{io, mem, ptr};
18 
19 use libc::{c_int, sigaction};
20 
21 use crate::linux::signal::Signal;
22 use crate::spin_rwlock::SpinningRwLock;
23 
24 pub(crate) struct SigAction {
25     pub(crate) sig_num: c_int,
26     pub(crate) act: sigaction,
27 }
28 
29 impl SigAction {
get_old_action(sig_num: c_int) -> io::Result<Self>30     pub(crate) fn get_old_action(sig_num: c_int) -> io::Result<Self> {
31         let mut old_act: libc::sigaction = unsafe { mem::zeroed() };
32         unsafe {
33             if libc::sigaction(sig_num, ptr::null(), &mut old_act) != 0 {
34                 return Err(io::Error::last_os_error());
35             }
36         }
37         Ok(SigAction {
38             sig_num,
39             act: old_act,
40         })
41     }
42 }
43 
44 pub(crate) struct SignalManager {
45     pub(crate) data: SpinningRwLock<HashMap<c_int, Signal>>,
46     pub(crate) race_old: SpinningRwLock<Option<SigAction>>,
47 }
48 
49 impl SignalManager {
50     // This function will be called inside a signal handler.
51     // Although a mutex Once is used, but the mutex will only be locked for once
52     // when initializing the SignalManager, which is outside of the signal
53     // handler.
get_instance() -> &'static SignalManager54     pub(crate) fn get_instance() -> &'static SignalManager {
55         static ONCE: Once = Once::new();
56         static mut GLOBAL_SIG_MANAGER: MaybeUninit<SignalManager> = MaybeUninit::uninit();
57 
58         unsafe {
59             ONCE.call_once(|| {
60                 GLOBAL_SIG_MANAGER = MaybeUninit::new(SignalManager {
61                     data: SpinningRwLock::new(HashMap::new()),
62                     race_old: SpinningRwLock::new(None),
63                 });
64             });
65             &*GLOBAL_SIG_MANAGER.as_ptr()
66         }
67     }
68 }
69