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