signal.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. mod signal_action;
  2. use alloc::collections::binary_heap::BinaryHeap;
  3. use alloc::sync::Arc;
  4. use core::cmp::Reverse;
  5. use core::task::Waker;
  6. use eonix_hal::fpu::FpuState;
  7. use eonix_hal::traits::trap::RawTrapContext;
  8. use eonix_hal::trap::TrapContext;
  9. use eonix_runtime::scheduler::Runtime;
  10. use eonix_sync::AsProof as _;
  11. use intrusive_collections::UnsafeRef;
  12. use posix_types::signal::{SigSet, Signal};
  13. use posix_types::{SIGNAL_IGNORE, SIGNAL_NOW, SIGNAL_STOP};
  14. pub use signal_action::SignalAction;
  15. use signal_action::SignalActionList;
  16. use super::{ProcessList, Thread, WaitObject, WaitType};
  17. use crate::kernel::constants::{EFAULT, EINVAL};
  18. use crate::kernel::user::UserPointer;
  19. use crate::prelude::*;
  20. pub(self) const SAVED_DATA_SIZE: usize =
  21. size_of::<TrapContext>() + size_of::<FpuState>() + size_of::<SigSet>();
  22. struct SignalListInner {
  23. mask: SigSet,
  24. pending: BinaryHeap<Reverse<Signal>>,
  25. signal_waker: Option<UnsafeRef<dyn Fn() + Send + Sync>>,
  26. stop_waker: Option<Waker>,
  27. // TODO!!!!!: Signal disposition should be per-process.
  28. actions: Arc<SignalActionList>,
  29. }
  30. pub struct SignalList {
  31. inner: Spin<SignalListInner>,
  32. }
  33. impl Clone for SignalList {
  34. fn clone(&self) -> Self {
  35. let inner = self.inner.lock();
  36. debug_assert!(
  37. inner.stop_waker.is_none(),
  38. "We should not have a stop waker here"
  39. );
  40. Self {
  41. inner: Spin::new(SignalListInner {
  42. mask: inner.mask,
  43. pending: BinaryHeap::new(),
  44. signal_waker: None,
  45. stop_waker: None,
  46. actions: inner.actions.clone(),
  47. }),
  48. }
  49. }
  50. }
  51. #[derive(Debug, Clone, Copy)]
  52. pub enum RaiseResult {
  53. Finished,
  54. Masked,
  55. }
  56. impl SignalListInner {
  57. fn pop(&mut self) -> Option<Signal> {
  58. self.pending.pop().map(|Reverse(signal)| signal)
  59. }
  60. fn raise(&mut self, signal: Signal) -> RaiseResult {
  61. if self.mask.include(signal) {
  62. return RaiseResult::Masked;
  63. }
  64. match (signal, self.actions.get(signal)) {
  65. (_, SignalAction::Ignore) => {}
  66. (SIGNAL_IGNORE!(), SignalAction::Default) => {}
  67. _ => {
  68. self.mask.mask(SigSet::from(signal));
  69. self.pending.push(Reverse(signal));
  70. if matches!(signal, Signal::SIGCONT) {
  71. self.stop_waker.take().map(|waker| waker.wake());
  72. } else {
  73. // If we don't have a waker here, we are not permitted to be woken up.
  74. // We would run in the end anyway.
  75. if let Some(waker) = self.signal_waker.take() {
  76. waker();
  77. }
  78. }
  79. }
  80. }
  81. RaiseResult::Finished
  82. }
  83. }
  84. impl SignalList {
  85. pub fn new() -> Self {
  86. Self {
  87. inner: Spin::new(SignalListInner {
  88. mask: SigSet::empty(),
  89. pending: BinaryHeap::new(),
  90. signal_waker: None,
  91. stop_waker: None,
  92. actions: Arc::new(SignalActionList::new()),
  93. }),
  94. }
  95. }
  96. pub fn get_mask(&self) -> SigSet {
  97. self.inner.lock().mask
  98. }
  99. pub fn set_mask(&self, mask: SigSet) {
  100. self.inner.lock().mask = mask;
  101. }
  102. pub fn mask(&self, mask: SigSet) {
  103. self.inner.lock().mask.mask(mask)
  104. }
  105. pub fn unmask(&self, mask: SigSet) {
  106. self.inner.lock().mask.unmask(mask)
  107. }
  108. pub fn set_action(
  109. &self,
  110. signal: Signal,
  111. action: SignalAction,
  112. ) -> KResult<()> {
  113. if matches!(signal, SIGNAL_NOW!()) {
  114. return Err(EINVAL);
  115. }
  116. self.inner.lock().actions.set(signal, action);
  117. Ok(())
  118. }
  119. pub fn get_action(&self, signal: Signal) -> SignalAction {
  120. self.inner.lock().actions.get(signal)
  121. }
  122. pub fn set_signal_waker(
  123. &self,
  124. waker: Option<UnsafeRef<dyn Fn() + Send + Sync>>,
  125. ) {
  126. let mut inner = self.inner.lock();
  127. inner.signal_waker = waker;
  128. }
  129. /// Clear all signals except for `SIG_IGN`.
  130. /// This is used when `execve` is called.
  131. pub fn clear_non_ignore(&self) {
  132. self.inner.lock().actions.remove_non_ignore();
  133. }
  134. /// Clear all pending signals.
  135. /// This is used when `fork` is called.
  136. pub fn clear_pending(&self) {
  137. self.inner.lock().pending.clear()
  138. }
  139. pub fn has_pending_signal(&self) -> bool {
  140. !self.inner.lock().pending.is_empty()
  141. }
  142. /// Do not use this, use `Thread::raise` instead.
  143. pub(super) fn raise(&self, signal: Signal) -> RaiseResult {
  144. self.inner.lock().raise(signal)
  145. }
  146. /// Handle signals in the context of `Thread::current()`.
  147. pub async fn handle(
  148. &self,
  149. trap_ctx: &mut TrapContext,
  150. fpu_state: &mut FpuState,
  151. ) {
  152. loop {
  153. let signal = {
  154. let Some(signal) = self.inner.lock().pop() else { return };
  155. let handler = self.inner.lock().actions.get(signal);
  156. if let SignalAction::SimpleHandler { mask, .. } = &handler {
  157. let old_mask = {
  158. let mut inner = self.inner.lock();
  159. let old_mask = inner.mask;
  160. inner.mask.mask(*mask);
  161. old_mask
  162. };
  163. let result =
  164. handler.handle(signal, old_mask, trap_ctx, fpu_state);
  165. if result.is_err() {
  166. self.inner.lock().mask = old_mask;
  167. }
  168. match result {
  169. Err(EFAULT) => self.inner.lock().raise(Signal::SIGSEGV),
  170. Err(_) => self.inner.lock().raise(Signal::SIGSYS),
  171. Ok(()) => return,
  172. };
  173. continue;
  174. }
  175. // TODO: The default signal handling process should be atomic.
  176. // Default actions include stopping the thread, continuing the thread and
  177. // terminating the process. All these actions will block the thread or return
  178. // to the thread immediately. So we can unmask these signals now.
  179. self.inner.lock().mask.unmask(SigSet::from(signal));
  180. signal
  181. };
  182. // Default actions.
  183. match signal {
  184. SIGNAL_IGNORE!() => {}
  185. Signal::SIGCONT => {
  186. // SIGCONT wakeup is done in `raise()`. So no further action needed here.
  187. }
  188. SIGNAL_STOP!() => {
  189. let thread = Thread::current();
  190. if let Some(parent) = thread.process.parent.load() {
  191. parent.notify(
  192. Some(Signal::SIGCHLD),
  193. WaitObject {
  194. pid: thread.process.pid,
  195. code: WaitType::Stopped(signal),
  196. },
  197. ProcessList::get().read().await.prove(),
  198. );
  199. }
  200. // `SIGSTOP` can only be waken up by `SIGCONT` or `SIGKILL`.
  201. // SAFETY: Preempt disabled above.
  202. Runtime::block_till_woken(|waker| {
  203. let mut inner = self.inner.lock();
  204. let old_waker = inner.stop_waker.replace(waker.clone());
  205. assert!(
  206. old_waker.is_none(),
  207. "We should not have a waker here"
  208. );
  209. })
  210. .await;
  211. if let Some(parent) = thread.process.parent.load() {
  212. parent.notify(
  213. Some(Signal::SIGCHLD),
  214. WaitObject {
  215. pid: thread.process.pid,
  216. code: WaitType::Continued,
  217. },
  218. ProcessList::get().read().await.prove(),
  219. );
  220. }
  221. }
  222. signal => {
  223. // Default to terminate the thread.
  224. Thread::current().force_kill(signal);
  225. return;
  226. }
  227. }
  228. }
  229. }
  230. /// Load the signal mask, fpu state and trap context from the user stack.
  231. pub fn restore(
  232. &self,
  233. trap_ctx: &mut TrapContext,
  234. fpu_state: &mut FpuState,
  235. old_sigreturn: bool,
  236. ) -> KResult<()> {
  237. #[cfg(not(any(
  238. target_arch = "x86_64",
  239. target_arch = "riscv64",
  240. target_arch = "loongarch64"
  241. )))]
  242. compile_error!("`restore` is not implemented for this architecture");
  243. #[cfg(target_arch = "x86_64")]
  244. let old_trap_ctx_vaddr = {
  245. let mut old_trap_ctx_vaddr = trap_ctx.get_stack_pointer() + 16;
  246. if old_sigreturn {
  247. // Old sigreturn will pop 4 bytes off the stack. We sub them back.
  248. use posix_types::ctypes::Long;
  249. old_trap_ctx_vaddr -= size_of::<Long>();
  250. }
  251. old_trap_ctx_vaddr
  252. };
  253. #[cfg(any(target_arch = "riscv64", target_arch = "loongarch64"))]
  254. let old_trap_ctx_vaddr = {
  255. debug_assert!(
  256. !old_sigreturn,
  257. "Old sigreturn is not supported on RISC-V and LoongArch64"
  258. );
  259. trap_ctx.get_stack_pointer()
  260. };
  261. let old_fpu_state_vaddr = old_trap_ctx_vaddr + size_of::<TrapContext>();
  262. let old_mask_vaddr = old_fpu_state_vaddr + size_of::<FpuState>();
  263. *trap_ctx = UserPointer::<TrapContext>::with_addr(old_trap_ctx_vaddr)?
  264. .read()?;
  265. // Make sure that at least we won't crash the kernel.
  266. if !trap_ctx.is_user_mode() || !trap_ctx.is_interrupt_enabled() {
  267. return Err(EFAULT)?;
  268. }
  269. *fpu_state =
  270. UserPointer::<FpuState>::with_addr(old_fpu_state_vaddr)?.read()?;
  271. self.inner.lock().mask =
  272. UserPointer::<SigSet>::with_addr(old_mask_vaddr)?.read()?;
  273. Ok(())
  274. }
  275. }
  276. impl SignalList {
  277. pub fn new_cloned(other: &Self) -> Self {
  278. let inner = other.inner.lock();
  279. debug_assert!(
  280. inner.stop_waker.is_none(),
  281. "We should not have a stop waker here"
  282. );
  283. Self {
  284. inner: Spin::new(SignalListInner {
  285. mask: inner.mask,
  286. pending: BinaryHeap::new(),
  287. signal_waker: None,
  288. stop_waker: None,
  289. actions: SignalActionList::new_cloned(&inner.actions),
  290. }),
  291. }
  292. }
  293. // shared only signal actions
  294. pub fn new_shared(other: &Self) -> Self {
  295. let inner = other.inner.lock();
  296. debug_assert!(
  297. inner.stop_waker.is_none(),
  298. "We should not have a stop waker here"
  299. );
  300. Self {
  301. inner: Spin::new(SignalListInner {
  302. mask: inner.mask,
  303. pending: BinaryHeap::new(),
  304. signal_waker: None,
  305. stop_waker: None,
  306. actions: SignalActionList::new_shared(&inner.actions),
  307. }),
  308. }
  309. }
  310. }