mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-01-30 17:11:47 -05:00
clone: add all tasks to process task list
This prevents a bug where `sys_exit` calls `exit_group` for the thread's process, even when there are still active threads.
This commit is contained in:
committed by
Ashwin Naren
parent
0f566f37e7
commit
116a1adbd0
@@ -304,11 +304,11 @@ State:\t{state}
|
||||
Tgid:\t{tgid}
|
||||
FDSize:\t{fd_size}
|
||||
Pid:\t{pid}
|
||||
Threads:\t{threads}\n",
|
||||
Threads:\t{tasks}\n",
|
||||
name = name.as_str(),
|
||||
tgid = task.process.tgid,
|
||||
fd_size = task.fd_table.lock_save_irq().len(),
|
||||
threads = task.process.threads.lock_save_irq().len(),
|
||||
tasks = task.process.tasks.lock_save_irq().len(),
|
||||
),
|
||||
TaskFileType::Comm => format!("{name}\n", name = name.as_str()),
|
||||
TaskFileType::State => format!("{state}\n"),
|
||||
|
||||
@@ -166,7 +166,14 @@ pub async fn sys_clone(
|
||||
|
||||
let tid = new_task.tid;
|
||||
|
||||
sched::insert_task_cross_cpu(Arc::new(new_task));
|
||||
let task = Arc::new(new_task);
|
||||
|
||||
sched::insert_task_cross_cpu(task.clone());
|
||||
|
||||
task.process
|
||||
.tasks
|
||||
.lock_save_irq()
|
||||
.insert(tid, Arc::downgrade(&task));
|
||||
|
||||
// Honour CLONE_*SETTID semantics for the parent and (shared-VM) child.
|
||||
if flags.contains(CloneFlags::CLONE_PARENT_SETTID) && !parent_tidptr.is_null() {
|
||||
|
||||
@@ -43,7 +43,7 @@ pub fn do_exit_group(exit_code: ChildState) {
|
||||
|
||||
// Signal all other threads in the group to terminate. We iterate over Weak
|
||||
// pointers and upgrade them.
|
||||
for thread_weak in process.threads.lock_save_irq().values() {
|
||||
for thread_weak in process.tasks.lock_save_irq().values() {
|
||||
if let Some(other_thread) = thread_weak.upgrade() {
|
||||
// Don't signal ourselves
|
||||
if other_thread.tid != task.tid {
|
||||
@@ -117,18 +117,18 @@ pub async fn sys_exit(exit_code: usize) -> Result<usize> {
|
||||
}
|
||||
|
||||
let process = Arc::clone(&task.process);
|
||||
let mut thread_lock = process.threads.lock_save_irq();
|
||||
let mut tasks_lock = process.tasks.lock_save_irq();
|
||||
|
||||
// How many threads are left? We must count live ones.
|
||||
let live_threads = thread_lock
|
||||
let live_tasks = tasks_lock
|
||||
.values()
|
||||
.filter(|t| t.upgrade().is_some())
|
||||
.count();
|
||||
|
||||
if live_threads <= 1 {
|
||||
// We are the last thread. This is equivalent to an exit_group. The
|
||||
// exit code for an implicit exit_group is often 0.
|
||||
drop(thread_lock);
|
||||
if live_tasks <= 1 {
|
||||
// We are the last task. This is equivalent to an exit_group. The exit
|
||||
// code for an implicit exit_group is often 0.
|
||||
drop(tasks_lock);
|
||||
|
||||
// NOTE: We don't need to worry about a race condition here. Since
|
||||
// we've established we're the only thread and we're executing a
|
||||
@@ -144,7 +144,7 @@ pub async fn sys_exit(exit_code: usize) -> Result<usize> {
|
||||
*task.state.lock_save_irq() = TaskState::Finished;
|
||||
|
||||
// Remove ourself from the process's thread list.
|
||||
thread_lock.remove(&task.tid);
|
||||
tasks_lock.remove(&task.tid);
|
||||
|
||||
// 3. This thread stops executing forever. The task struct will be
|
||||
// deallocated when the last Arc<Task> is dropped (e.g., by the
|
||||
|
||||
@@ -94,7 +94,7 @@ pub struct ThreadGroup {
|
||||
pub umask: SpinLock<u32>,
|
||||
pub parent: SpinLock<Option<Weak<ThreadGroup>>>,
|
||||
pub children: SpinLock<BTreeMap<Tgid, Arc<ThreadGroup>>>,
|
||||
pub threads: SpinLock<BTreeMap<Tid, Weak<Task>>>,
|
||||
pub tasks: SpinLock<BTreeMap<Tid, Weak<Task>>>,
|
||||
pub signals: Arc<SpinLock<SignalState>>,
|
||||
pub rsrc_lim: Arc<SpinLock<ResourceLimits>>,
|
||||
pub pending_signals: SpinLock<SigSet>,
|
||||
|
||||
@@ -73,7 +73,7 @@ impl ThreadGroupBuilder {
|
||||
// couldn't then differentiate between a child and a parent.
|
||||
next_tid: AtomicU32::new(1),
|
||||
state: SpinLock::new(ProcessState::Running),
|
||||
threads: SpinLock::new(BTreeMap::new()),
|
||||
tasks: SpinLock::new(BTreeMap::new()),
|
||||
});
|
||||
|
||||
TG_LIST
|
||||
|
||||
@@ -82,7 +82,7 @@ pub fn sys_tkill(tid: PidT, signal: UserSigId) -> Result<usize> {
|
||||
} else {
|
||||
let task = current_task
|
||||
.process
|
||||
.threads
|
||||
.tasks
|
||||
.lock_save_irq()
|
||||
.get(&target_tid)
|
||||
.and_then(|t| t.upgrade())
|
||||
|
||||
@@ -255,7 +255,7 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
parent.signals.lock_save_irq().set_pending(SigId::SIGCHLD);
|
||||
}
|
||||
|
||||
for thr_weak in process.threads.lock_save_irq().values() {
|
||||
for thr_weak in process.tasks.lock_save_irq().values() {
|
||||
if let Some(thr) = thr_weak.upgrade() {
|
||||
*thr.state.lock_save_irq() = TaskState::Stopped;
|
||||
}
|
||||
@@ -268,7 +268,7 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
|
||||
let process = &task.process;
|
||||
|
||||
// Wake up all sleeping threads in the process.
|
||||
for thr_weak in process.threads.lock_save_irq().values() {
|
||||
for thr_weak in process.tasks.lock_save_irq().values() {
|
||||
if let Some(thr) = thr_weak.upgrade() {
|
||||
let mut st = thr.state.lock_save_irq();
|
||||
if *st == TaskState::Sleeping {
|
||||
|
||||
Reference in New Issue
Block a user