123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643 |
- use core::sync::atomic::compiler_fence;
- use alloc::sync::Arc;
- use log::warn;
- use system_error::SystemError;
- use crate::{
- arch::ipc::signal::{SigCode, SigFlags, SigSet, Signal},
- ipc::signal_types::SigactionType,
- libs::spinlock::SpinLockGuard,
- process::{
- pid::PidType, Pid, ProcessControlBlock, ProcessFlags, ProcessManager, ProcessSignalInfo,
- },
- };
- use super::signal_types::{
- SaHandlerType, SigInfo, SigType, Sigaction, SignalStruct, SIG_KERNEL_STOP_MASK,
- };
- impl Signal {
- pub fn signal_pending_state(
- interruptible: bool,
- task_wake_kill: bool,
- pcb: &Arc<ProcessControlBlock>,
- ) -> bool {
- if !interruptible && !task_wake_kill {
- return false;
- }
- if !pcb.has_pending_signal_fast() {
- return false;
- }
- return interruptible || Self::fatal_signal_pending(pcb);
- }
-
- pub fn fatal_signal_pending(pcb: &Arc<ProcessControlBlock>) -> bool {
- let guard = pcb.sig_info_irqsave();
- if guard
- .sig_pending()
- .signal()
- .contains(Signal::SIGKILL.into())
- {
- return true;
- }
- return false;
- }
-
-
-
-
-
-
-
- pub fn send_signal_info(
- &self,
- info: Option<&mut SigInfo>,
- pid: Pid,
- ) -> Result<i32, SystemError> {
-
-
-
-
-
-
- if pid.lt(&Pid::from(0)) {
- warn!("Kill operation not support: pid={:?}", pid);
- return Err(SystemError::ENOSYS);
- }
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
- if !self.is_valid() {
- return Err(SystemError::EINVAL);
- }
- let mut retval = Err(SystemError::ESRCH);
- let pcb = ProcessManager::find(pid);
- if pcb.is_none() {
- warn!("No such process.");
- return retval;
- }
- let pcb = pcb.unwrap();
-
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
- retval = self.send_signal(info, pcb.clone(), PidType::PID);
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
- return retval;
- }
-
-
-
-
- fn send_signal(
- &self,
- info: Option<&mut SigInfo>,
- pcb: Arc<ProcessControlBlock>,
- pt: PidType,
- ) -> Result<i32, SystemError> {
-
- let mut force_send = false;
-
- if let Some(ref siginfo) = info {
- force_send = matches!(siginfo.sig_code(), SigCode::Kernel);
- } else {
-
-
- }
- if !self.prepare_sianal(pcb.clone(), force_send) {
- return Ok(0);
- }
-
- let pcb_info = pcb.sig_info_irqsave();
- let pending = if matches!(pt, PidType::PID) {
- pcb_info.sig_shared_pending()
- } else {
- pcb_info.sig_pending()
- };
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
- if matches!(self, Signal::SIGKILL) || pcb.flags().contains(ProcessFlags::KTHREAD) {
-
- drop(pcb_info);
- self.complete_signal(pcb.clone(), pt);
- }
-
- else if !self.is_rt_signal() && pending.queue().find(*self).0.is_some() {
- return Ok(0);
- } else {
-
-
- let new_sig_info = match info {
- Some(siginfo) => {
-
- *siginfo
- }
- None => {
-
- SigInfo::new(
- *self,
- 0,
- SigCode::User,
- SigType::Kill(ProcessManager::current_pcb().pid()),
- )
- }
- };
- drop(pcb_info);
- pcb.sig_info_mut()
- .sig_pending_mut()
- .queue_mut()
- .q
- .push(new_sig_info);
-
- self.complete_signal(pcb.clone(), pt);
- }
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
- return Ok(0);
- }
-
-
-
-
-
- #[allow(clippy::if_same_then_else)]
- fn complete_signal(&self, pcb: Arc<ProcessControlBlock>, pt: PidType) {
-
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
-
-
-
- let target_pcb: Option<Arc<ProcessControlBlock>>;
-
- if self.wants_signal(pcb.clone()) {
-
-
- pcb.sig_info_mut()
- .sig_pending_mut()
- .signal_mut()
- .insert((*self).into());
- target_pcb = Some(pcb.clone());
- } else if pt == PidType::PID {
-
- return;
- } else {
-
- return;
- }
-
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
- if let Some(target_pcb) = target_pcb {
- let guard = target_pcb.sig_struct();
- signal_wake_up(target_pcb.clone(), guard, *self == Signal::SIGKILL);
- }
- }
-
-
-
-
- #[inline]
- fn wants_signal(&self, pcb: Arc<ProcessControlBlock>) -> bool {
-
- if pcb
- .sig_info_irqsave()
- .sig_blocked()
- .contains((*self).into())
- {
- return false;
- }
-
- if pcb.flags().contains(ProcessFlags::EXITING) {
- return false;
- }
- if *self == Signal::SIGKILL {
- return true;
- }
- let state = pcb.sched_info().inner_lock_read_irqsave().state();
- if state.is_blocked() && (!state.is_blocked_interruptable()) {
- return false;
- }
-
-
- return pcb.sig_info_irqsave().sig_pending().signal().bits() == 0;
- }
-
-
- #[allow(dead_code)]
- #[inline]
- fn sig_fatal(&self, pcb: Arc<ProcessControlBlock>) -> bool {
- let action = pcb.sig_struct().handlers[*self as usize - 1].action();
-
- match action {
- SigactionType::SaHandler(handler) => handler.is_sig_default(),
- SigactionType::SaSigaction(sigaction) => sigaction.is_none(),
- }
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- fn prepare_sianal(&self, pcb: Arc<ProcessControlBlock>, _force: bool) -> bool {
- let flush: SigSet;
- if !(self.into_sigset() & SIG_KERNEL_STOP_MASK).is_empty() {
- flush = Signal::SIGCONT.into_sigset();
- pcb.sig_info_mut()
- .sig_shared_pending_mut()
- .flush_by_mask(&flush);
-
- } else if *self == Signal::SIGCONT {
- flush = SIG_KERNEL_STOP_MASK;
- assert!(!flush.is_empty());
- pcb.sig_info_mut()
- .sig_shared_pending_mut()
- .flush_by_mask(&flush);
- let _r = ProcessManager::wakeup_stop(&pcb);
-
-
- }
-
- if pcb
- .sig_info_irqsave()
- .sig_blocked()
- .contains(self.into_sigset())
- {
- return true;
- }
- return !pcb.sig_struct().handlers[*self as usize - 1].is_ignore();
-
- }
- }
- #[inline]
- fn signal_wake_up(pcb: Arc<ProcessControlBlock>, _guard: SpinLockGuard<SignalStruct>, fatal: bool) {
-
-
-
-
- let state = pcb.sched_info().inner_lock_read_irqsave().state();
- pcb.flags().insert(ProcessFlags::HAS_PENDING_SIGNAL);
- let mut wakeup_ok = true;
- if state.is_blocked_interruptable() {
- ProcessManager::wakeup(&pcb).unwrap_or_else(|e| {
- wakeup_ok = false;
- warn!(
- "Current pid: {:?}, signal_wake_up target {:?} error: {:?}",
- ProcessManager::current_pcb().pid(),
- pcb.pid(),
- e
- );
- });
- } else if state.is_stopped() {
- ProcessManager::wakeup_stop(&pcb).unwrap_or_else(|e| {
- wakeup_ok = false;
- warn!(
- "Current pid: {:?}, signal_wake_up target {:?} error: {:?}",
- ProcessManager::current_pcb().pid(),
- pcb.pid(),
- e
- );
- });
- } else {
- wakeup_ok = false;
- }
- if wakeup_ok {
- ProcessManager::kick(&pcb);
- } else if fatal {
- let _r = ProcessManager::wakeup(&pcb).map(|_| {
- ProcessManager::kick(&pcb);
- });
- }
- }
- fn has_pending_signals(sigset: &SigSet, blocked: &SigSet) -> bool {
- sigset.bits() & (!blocked.bits()) != 0
- }
- impl ProcessControlBlock {
-
-
- pub fn recalc_sigpending(&self, siginfo_guard: Option<&ProcessSignalInfo>) {
- if !self.recalc_sigpending_tsk(siginfo_guard) {
- self.flags().remove(ProcessFlags::HAS_PENDING_SIGNAL);
- }
- }
- fn recalc_sigpending_tsk(&self, siginfo_guard: Option<&ProcessSignalInfo>) -> bool {
- let mut _siginfo_tmp_guard = None;
- let siginfo = if let Some(siginfo_guard) = siginfo_guard {
- siginfo_guard
- } else {
- _siginfo_tmp_guard = Some(self.sig_info_irqsave());
- _siginfo_tmp_guard.as_ref().unwrap()
- };
- return siginfo.do_recalc_sigpending_tsk(self);
- }
- }
- impl ProcessSignalInfo {
- fn do_recalc_sigpending_tsk(&self, pcb: &ProcessControlBlock) -> bool {
- if has_pending_signals(&self.sig_pending().signal(), self.sig_blocked())
- || has_pending_signals(&self.sig_shared_pending().signal(), self.sig_blocked())
- {
- pcb.flags().insert(ProcessFlags::HAS_PENDING_SIGNAL);
- return true;
- }
-
- return false;
- }
- }
- pub fn restore_saved_sigmask() {
- if ProcessManager::current_pcb()
- .flags()
- .test_and_clear(ProcessFlags::RESTORE_SIG_MASK)
- {
- let saved = *ProcessManager::current_pcb()
- .sig_info_irqsave()
- .saved_sigmask();
- __set_current_blocked(&saved);
- }
- }
- pub fn flush_signal_handlers(pcb: Arc<ProcessControlBlock>, force_default: bool) {
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
-
- let actions = &mut pcb.sig_struct_irqsave().handlers;
- for sigaction in actions.iter_mut() {
- if force_default || !sigaction.is_ignore() {
- sigaction.set_action(SigactionType::SaHandler(SaHandlerType::Default));
- }
-
- sigaction.set_restorer(None);
- sigaction.mask_mut().remove(SigSet::all());
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
- }
- compiler_fence(core::sync::atomic::Ordering::SeqCst);
- }
- pub(super) fn do_sigaction(
- sig: Signal,
- act: Option<&mut Sigaction>,
- old_act: Option<&mut Sigaction>,
- ) -> Result<(), SystemError> {
- if sig == Signal::INVALID {
- return Err(SystemError::EINVAL);
- }
- let pcb = ProcessManager::current_pcb();
-
- let action: &mut Sigaction = &mut pcb.sig_struct().handlers[sig as usize - 1];
-
-
-
-
-
- let old_act: Option<&mut Sigaction> = {
- if let Some(oa) = old_act {
- *(oa) = *action;
- Some(oa)
- } else {
- None
- }
- };
-
- let act = {
- if let Some(ac) = act {
- *ac.flags_mut() &= SigFlags::SA_ALL;
- Some(ac)
- } else {
- None
- }
- };
- if let Some(act) = old_act {
- *act.flags_mut() &= SigFlags::SA_ALL;
- }
- if let Some(ac) = act {
-
- ac.mask_mut()
- .remove(<Signal as Into<SigSet>>::into(Signal::SIGKILL) | Signal::SIGSTOP.into());
-
- *action = *ac;
-
- if action.is_ignore() {
- let mut mask: SigSet = SigSet::from_bits_truncate(0);
- mask.insert(sig.into());
- pcb.sig_info_mut().sig_pending_mut().flush_by_mask(&mask);
-
- }
- }
- return Ok(());
- }
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
- pub enum SigHow {
- Block = 0,
- Unblock = 1,
- SetMask = 2,
- }
- impl TryFrom<i32> for SigHow {
- type Error = SystemError;
- fn try_from(value: i32) -> Result<Self, Self::Error> {
- match value {
- 0 => Ok(SigHow::Block),
- 1 => Ok(SigHow::Unblock),
- 2 => Ok(SigHow::SetMask),
- _ => Err(SystemError::EINVAL),
- }
- }
- }
- fn __set_task_blocked(pcb: &Arc<ProcessControlBlock>, new_set: &SigSet) {
-
- if pcb.has_pending_signal() {
- let mut newblocked = *new_set;
- let guard = pcb.sig_info_irqsave();
- newblocked.remove(*guard.sig_blocked());
- drop(guard);
-
- if let Some(group_leader) = pcb.threads_read_irqsave().group_leader() {
- retarget_shared_pending(group_leader, newblocked);
- }
- }
- *pcb.sig_info_mut().sig_block_mut() = *new_set;
- pcb.recalc_sigpending(None);
- }
- fn __set_current_blocked(new_set: &SigSet) {
- let pcb = ProcessManager::current_pcb();
-
- if pcb.sig_info_irqsave().sig_blocked().eq(new_set) {
- return;
- }
- let guard: SpinLockGuard<'_, SignalStruct> = pcb.sig_struct_irqsave();
- __set_task_blocked(&pcb, new_set);
- drop(guard);
- }
- fn retarget_shared_pending(pcb: Arc<ProcessControlBlock>, which: SigSet) {
- let retarget = pcb.sig_info_irqsave().sig_shared_pending().signal();
- retarget.intersects(which);
- if retarget.is_empty() {
- return;
- }
-
- let thread_handling_function = |pcb: Arc<ProcessControlBlock>, retarget: &SigSet| {
- if retarget.is_empty() {
- return;
- }
- if pcb.flags().contains(ProcessFlags::EXITING) {
- return;
- }
- let blocked = pcb.sig_info_irqsave().sig_shared_pending().signal();
- if retarget.difference(blocked).is_empty() {
- return;
- }
- retarget.intersects(blocked);
- if !pcb.has_pending_signal() {
- let guard = pcb.sig_struct_irqsave();
- signal_wake_up(pcb.clone(), guard, false);
- }
-
-
- };
-
- let tgid = pcb.tgid();
- for &pid in pcb.children_read_irqsave().iter() {
- if let Some(child) = ProcessManager::find(pid) {
- if child.tgid() == tgid {
- thread_handling_function(child, &retarget);
- }
- }
- }
-
- }
- pub fn set_current_blocked(new_set: &mut SigSet) {
- let to_remove: SigSet =
- <Signal as Into<SigSet>>::into(Signal::SIGKILL) | Signal::SIGSTOP.into();
- new_set.remove(to_remove);
- __set_current_blocked(new_set);
- }
- pub fn set_sigprocmask(how: SigHow, set: SigSet) -> Result<SigSet, SystemError> {
- let pcb: Arc<ProcessControlBlock> = ProcessManager::current_pcb();
- let guard = pcb.sig_info_irqsave();
- let oset = *guard.sig_blocked();
- let mut res_set = oset;
- drop(guard);
- match how {
- SigHow::Block => {
-
- res_set.insert(set);
- }
- SigHow::Unblock => {
- res_set.remove(set);
- }
- SigHow::SetMask => {
-
- res_set = set;
- }
- }
- __set_current_blocked(&res_set);
- Ok(oset)
- }
|