mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-02-01 01:51:45 -05:00
This commit refactors the signal handling subsystem to address a bug in process creation and to improve the separation of concerns between signal delivery and signal disposition. 1. Fix Action Table Sharing: Previously, the signal action table was wrapped in an `Arc`, causing forked child processes to inadvertently share signal dispositions with the parent. `SignalActionState` now contains a direct `SigActionSet` and implements Clone, ensuring that processes receive a private copy of the action table upon fork/clone. 2. Decouple Signal Selection from Execution: The logic for selecting a pending signal has been moved from the disposition state into a new `take_signal` method on `OwnedTask`. This decouples the "taking" of a signal (respecting masks and priorities) from the "actioning" of that signal. This is a prerequisite for implementing ptrace. 3. Various cleanup bits: - Renamed `SignalState` to `SignalActionState` to more accurately reflect that it manages signal dispositions. - Removed the `pending` signal set out of the action state and directly into the `ThreadGroup` and `OwnedTask`. - Renamed `set_pending` to `set_signal` for consistency. - Simplified the signal delivery loop in `dispatch_userspace_task` using the new `take_signal` API.
96 lines
3.1 KiB
Rust
96 lines
3.1 KiB
Rust
use core::sync::atomic::{AtomicU32, AtomicU64};
|
|
|
|
use alloc::{collections::btree_map::BTreeMap, sync::Arc};
|
|
|
|
use crate::sync::SpinLock;
|
|
|
|
use super::{
|
|
Pgid, ProcessState, Sid, TG_LIST, Tgid, ThreadGroup,
|
|
rsrc_lim::ResourceLimits,
|
|
signal::{SigSet, SignalActionState},
|
|
wait::ChildNotifiers,
|
|
};
|
|
|
|
/// A builder for creating ThreadGroup instances.
|
|
pub struct ThreadGroupBuilder {
|
|
tgid: Tgid,
|
|
parent: Option<Arc<ThreadGroup>>,
|
|
umask: Option<u32>,
|
|
pri: Option<i8>,
|
|
sigstate: Option<Arc<SpinLock<SignalActionState>>>,
|
|
rsrc_lim: Option<Arc<SpinLock<ResourceLimits>>>,
|
|
}
|
|
|
|
impl ThreadGroupBuilder {
|
|
/// Creates a new ThreadGroupBuilder with the mandatory thread group ID.
|
|
pub fn new(tgid: Tgid) -> Self {
|
|
ThreadGroupBuilder {
|
|
tgid,
|
|
parent: None,
|
|
umask: None,
|
|
sigstate: None,
|
|
rsrc_lim: None,
|
|
pri: None,
|
|
}
|
|
}
|
|
|
|
/// Sets the parent of the thread group.
|
|
pub fn with_parent(mut self, parent: Arc<ThreadGroup>) -> Self {
|
|
self.parent = Some(parent);
|
|
self
|
|
}
|
|
|
|
/// Sets the signal state of the thread group.
|
|
pub fn with_sigstate(mut self, sigstate: Arc<SpinLock<SignalActionState>>) -> Self {
|
|
self.sigstate = Some(sigstate);
|
|
self
|
|
}
|
|
|
|
pub fn with_rsrc_lim(mut self, rsrc_lim: Arc<SpinLock<ResourceLimits>>) -> Self {
|
|
self.rsrc_lim = Some(rsrc_lim);
|
|
self
|
|
}
|
|
|
|
pub fn with_priority(mut self, priority: i8) -> Self {
|
|
self.pri = Some(priority);
|
|
self
|
|
}
|
|
|
|
/// Builds the ThreadGroup.
|
|
///
|
|
/// If a sigstate has not been provided, a default one will be created.
|
|
pub fn build(self) -> Arc<ThreadGroup> {
|
|
let ret = Arc::new(ThreadGroup {
|
|
tgid: self.tgid,
|
|
pgid: SpinLock::new(Pgid(self.tgid.value())),
|
|
sid: SpinLock::new(Sid(self.tgid.value())),
|
|
parent: SpinLock::new(self.parent.as_ref().map(Arc::downgrade)),
|
|
umask: SpinLock::new(self.umask.unwrap_or(0)),
|
|
children: SpinLock::new(BTreeMap::new()),
|
|
signals: self
|
|
.sigstate
|
|
.unwrap_or_else(|| Arc::new(SpinLock::new(SignalActionState::new_default()))),
|
|
rsrc_lim: self
|
|
.rsrc_lim
|
|
.unwrap_or_else(|| Arc::new(SpinLock::new(ResourceLimits::default()))),
|
|
pending_signals: SpinLock::new(SigSet::empty()),
|
|
child_notifiers: ChildNotifiers::new(),
|
|
priority: SpinLock::new(self.pri.unwrap_or(0)),
|
|
utime: AtomicU64::new(0),
|
|
stime: AtomicU64::new(0),
|
|
// Don't start from '0'. Since clone expects the parent to return
|
|
// the tid and the child to return '0', if we started from '0' we
|
|
// couldn't then differentiate between a child and a parent.
|
|
next_tid: AtomicU32::new(1),
|
|
state: SpinLock::new(ProcessState::Running),
|
|
tasks: SpinLock::new(BTreeMap::new()),
|
|
});
|
|
|
|
TG_LIST
|
|
.lock_save_irq()
|
|
.insert(self.tgid, Arc::downgrade(&ret));
|
|
|
|
ret
|
|
}
|
|
}
|