1cac7dca0Sopenharmony_ci// Copyright (c) 2023 Huawei Device Co., Ltd. 2cac7dca0Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 3cac7dca0Sopenharmony_ci// you may not use this file except in compliance with the License. 4cac7dca0Sopenharmony_ci// You may obtain a copy of the License at 5cac7dca0Sopenharmony_ci// 6cac7dca0Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 7cac7dca0Sopenharmony_ci// 8cac7dca0Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 9cac7dca0Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 10cac7dca0Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11cac7dca0Sopenharmony_ci// See the License for the specific language governing permissions and 12cac7dca0Sopenharmony_ci// limitations under the License. 13cac7dca0Sopenharmony_ci 14cac7dca0Sopenharmony_ci//! windows wrapping of signal syscall 15cac7dca0Sopenharmony_ci 16cac7dca0Sopenharmony_ciuse std::{io, mem}; 17cac7dca0Sopenharmony_ci 18cac7dca0Sopenharmony_ciuse libc::{c_int, sighandler_t, SIGFPE, SIG_DFL, SIG_ERR, SIG_GET, SIG_IGN}; 19cac7dca0Sopenharmony_ci 20cac7dca0Sopenharmony_ciuse crate::common::{siginfo_t, SigAction, Signal}; 21cac7dca0Sopenharmony_ciuse crate::sig_map::SigMap; 22cac7dca0Sopenharmony_ci 23cac7dca0Sopenharmony_ciimpl SigAction { 24cac7dca0Sopenharmony_ci pub(crate) fn get_old_action(sig_num: c_int) -> io::Result<Self> { 25cac7dca0Sopenharmony_ci let old_act = unsafe { libc::signal(sig_num, SIG_GET) }; 26cac7dca0Sopenharmony_ci if old_act == SIG_ERR as sighandler_t { 27cac7dca0Sopenharmony_ci return Err(io::Error::last_os_error()); 28cac7dca0Sopenharmony_ci } 29cac7dca0Sopenharmony_ci Ok(SigAction { 30cac7dca0Sopenharmony_ci sig_num, 31cac7dca0Sopenharmony_ci act: old_act, 32cac7dca0Sopenharmony_ci }) 33cac7dca0Sopenharmony_ci } 34cac7dca0Sopenharmony_ci} 35cac7dca0Sopenharmony_ci 36cac7dca0Sopenharmony_ciimpl Signal { 37cac7dca0Sopenharmony_ci pub(crate) fn replace_sigaction( 38cac7dca0Sopenharmony_ci sig_num: c_int, 39cac7dca0Sopenharmony_ci new_action: sighandler_t, 40cac7dca0Sopenharmony_ci ) -> io::Result<sighandler_t> { 41cac7dca0Sopenharmony_ci let old_act = unsafe { libc::signal(sig_num, new_action) }; 42cac7dca0Sopenharmony_ci 43cac7dca0Sopenharmony_ci if old_act == SIG_ERR as sighandler_t { 44cac7dca0Sopenharmony_ci return Err(io::Error::last_os_error()); 45cac7dca0Sopenharmony_ci } 46cac7dca0Sopenharmony_ci 47cac7dca0Sopenharmony_ci Ok(old_act) 48cac7dca0Sopenharmony_ci } 49cac7dca0Sopenharmony_ci} 50cac7dca0Sopenharmony_ci 51cac7dca0Sopenharmony_cipub(crate) extern "C" fn sig_handler(sig_num: c_int) { 52cac7dca0Sopenharmony_ci if sig_num != SIGFPE { 53cac7dca0Sopenharmony_ci let old = unsafe { libc::signal(sig_num, sig_handler as usize) }; 54cac7dca0Sopenharmony_ci if old == SIG_ERR as sighandler_t { 55cac7dca0Sopenharmony_ci unsafe { 56cac7dca0Sopenharmony_ci libc::abort(); 57cac7dca0Sopenharmony_ci } 58cac7dca0Sopenharmony_ci } 59cac7dca0Sopenharmony_ci } 60cac7dca0Sopenharmony_ci 61cac7dca0Sopenharmony_ci let sig_map = SigMap::get_instance(); 62cac7dca0Sopenharmony_ci let race_fallback = sig_map.race_old.read(); 63cac7dca0Sopenharmony_ci let data = sig_map.data.read(); 64cac7dca0Sopenharmony_ci 65cac7dca0Sopenharmony_ci if let Some(signal) = data.get(&sig_num) { 66cac7dca0Sopenharmony_ci if let Some(act) = &signal.new_act { 67cac7dca0Sopenharmony_ci act(&siginfo_t); 68cac7dca0Sopenharmony_ci } 69cac7dca0Sopenharmony_ci } else if let Some(fallback) = race_fallback.as_ref() { 70cac7dca0Sopenharmony_ci // There could be a race condition between swapping the old handler with the new 71cac7dca0Sopenharmony_ci // handler and storing the change back to the global during the register 72cac7dca0Sopenharmony_ci // procedure. Because of the race condition, the old handler and the new 73cac7dca0Sopenharmony_ci // action could both not get executed. In order to prevent this, we 74cac7dca0Sopenharmony_ci // store the old handler into global before swapping the handler in 75cac7dca0Sopenharmony_ci // register. And during the handler execution, if the the action 76cac7dca0Sopenharmony_ci // of the signal cannot be found, we execute this old handler instead if the 77cac7dca0Sopenharmony_ci // sig_num matches. 78cac7dca0Sopenharmony_ci if fallback.sig_num == sig_num { 79cac7dca0Sopenharmony_ci execute_act(fallback.act, sig_num); 80cac7dca0Sopenharmony_ci } 81cac7dca0Sopenharmony_ci } 82cac7dca0Sopenharmony_ci} 83cac7dca0Sopenharmony_ci 84cac7dca0Sopenharmony_cifn execute_act(act: sighandler_t, sig_num: c_int) { 85cac7dca0Sopenharmony_ci if act != 0 && act != SIG_DFL && act != SIG_IGN { 86cac7dca0Sopenharmony_ci unsafe { 87cac7dca0Sopenharmony_ci let action = mem::transmute::<usize, extern "C" fn(c_int)>(act); 88cac7dca0Sopenharmony_ci action(sig_num); 89cac7dca0Sopenharmony_ci } 90cac7dca0Sopenharmony_ci } 91cac7dca0Sopenharmony_ci} 92