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 //! windows wrapping of signal syscall
15 
16 use std::{io, mem};
17 
18 use libc::{c_int, sighandler_t, SIGFPE, SIG_DFL, SIG_ERR, SIG_GET, SIG_IGN};
19 
20 use crate::common::{siginfo_t, SigAction, Signal};
21 use crate::sig_map::SigMap;
22 
23 impl SigAction {
get_old_action(sig_num: c_int) -> io::Result<Self>24     pub(crate) fn get_old_action(sig_num: c_int) -> io::Result<Self> {
25         let old_act = unsafe { libc::signal(sig_num, SIG_GET) };
26         if old_act == SIG_ERR as sighandler_t {
27             return Err(io::Error::last_os_error());
28         }
29         Ok(SigAction {
30             sig_num,
31             act: old_act,
32         })
33     }
34 }
35 
36 impl Signal {
replace_sigaction( sig_num: c_int, new_action: sighandler_t, ) -> io::Result<sighandler_t>37     pub(crate) fn replace_sigaction(
38         sig_num: c_int,
39         new_action: sighandler_t,
40     ) -> io::Result<sighandler_t> {
41         let old_act = unsafe { libc::signal(sig_num, new_action) };
42 
43         if old_act == SIG_ERR as sighandler_t {
44             return Err(io::Error::last_os_error());
45         }
46 
47         Ok(old_act)
48     }
49 }
50 
sig_handler(sig_num: c_int)51 pub(crate) extern "C" fn sig_handler(sig_num: c_int) {
52     if sig_num != SIGFPE {
53         let old = unsafe { libc::signal(sig_num, sig_handler as usize) };
54         if old == SIG_ERR as sighandler_t {
55             unsafe {
56                 libc::abort();
57             }
58         }
59     }
60 
61     let sig_map = SigMap::get_instance();
62     let race_fallback = sig_map.race_old.read();
63     let data = sig_map.data.read();
64 
65     if let Some(signal) = data.get(&sig_num) {
66         if let Some(act) = &signal.new_act {
67             act(&siginfo_t);
68         }
69     } else if let Some(fallback) = race_fallback.as_ref() {
70         // There could be a race condition between swapping the old handler with the new
71         // handler and storing the change back to the global during the register
72         // procedure. Because of the race condition, the old handler and the new
73         // action could both not get executed. In order to prevent this, we
74         // store the old handler into global before swapping the handler in
75         // register. And during the handler execution, if the the action
76         // of the signal cannot be found, we execute this old handler instead if the
77         // sig_num matches.
78         if fallback.sig_num == sig_num {
79             execute_act(fallback.act, sig_num);
80         }
81     }
82 }
83 
execute_act(act: sighandler_t, sig_num: c_int)84 fn execute_act(act: sighandler_t, sig_num: c_int) {
85     if act != 0 && act != SIG_DFL && act != SIG_IGN {
86         unsafe {
87             let action = mem::transmute::<usize, extern "C" fn(c_int)>(act);
88             action(sig_num);
89         }
90     }
91 }
92