From b6349e21cb7eb7bc3f89d96c8abaa4832532c493 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 12 Jun 2013 01:35:31 +0200 Subject: [PATCH] Implement sending signals to process groups. --- sortix/include/sortix/kernel/process.h | 4 +- sortix/process.cpp | 108 +++++++++++++------------ sortix/thread.cpp | 7 +- 3 files changed, 65 insertions(+), 54 deletions(-) diff --git a/sortix/include/sortix/kernel/process.h b/sortix/include/sortix/kernel/process.h index 6af52362..78d6c334 100644 --- a/sortix/include/sortix/kernel/process.h +++ b/sortix/include/sortix/kernel/process.h @@ -77,7 +77,6 @@ public: class Process { friend void Process__OnLastThreadExit(void*); -friend void Process__LastPrayerFinalize(void*); public: Process(); @@ -177,6 +176,7 @@ public: void Exit(int status); pid_t Wait(pid_t pid, int* status, int options); bool DeliverSignal(int signum); + bool DeliverGroupSignal(int signum); void OnThreadDestruction(Thread* thread); int GetParentProcessId(); void AddChildProcess(Process* child); @@ -192,7 +192,7 @@ private: CPU::InterruptRegisters* regs); void OnLastThreadExit(); void LastPrayer(); - void LastPrayerFinalize(); + void NotifyMemberExit(Process* child); void NotifyChildExit(Process* child, bool zombify); void NotifyNewZombies(); void DeleteTimers(); diff --git a/sortix/process.cpp b/sortix/process.cpp index e161dfe5..f83b40d4 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -341,41 +341,14 @@ void Process::LastPrayer() iszombie = true; - // If this is a process group leader of a group containing other processes, - // then we have to wait until we are the only member and then terminate. - kthread_mutex_lock(&groupchildlock); - bool group_leader = group == this; - kthread_mutex_unlock(&groupchildlock); - if ( group_leader ) - { - grouplimbo = true; - NotifyLeftProcessGroup(); - return; - } - - LastPrayerFinalize(); -} - -void Process__LastPrayerFinalize(void* user) -{ - return ((Process*) user)->LastPrayerFinalize(); -} - -void Process::NotifyLeftProcessGroup() -{ - ScopedLock parentlock(&groupparentlock); - if ( !grouplimbo ) - return; - if ( groupprev || groupnext ) - return; - grouplimbo = false; - Worker::Schedule(Process__LastPrayerFinalize, this); -} - -void Process::LastPrayerFinalize() -{ bool zombify = !nozombify; + // Remove ourself from our process group. + kthread_mutex_lock(&groupchildlock); + if ( group ) + group->NotifyMemberExit(this); + kthread_mutex_unlock(&groupchildlock); + // This class instance will be destroyed by our parent process when it // has received and acknowledged our death. kthread_mutex_lock(&parentlock); @@ -385,7 +358,14 @@ void Process::LastPrayerFinalize() // If nobody is waiting for us, then simply commit suicide. if ( !zombify ) - delete this; + { + kthread_mutex_lock(&groupparentlock); + bool in_limbo = groupfirst || (grouplimbo = true); + kthread_mutex_unlock(&groupparentlock); + + if ( !in_limbo ) + delete this; + } } void Process::ResetAddressSpace() @@ -403,6 +383,33 @@ void Process::ResetAddressSpace() segments = NULL; } +void Process::NotifyMemberExit(Process* child) +{ + assert(child->group == this); + kthread_mutex_lock(&groupparentlock); + if ( child->groupprev ) + child->groupprev->groupnext = child->groupnext; + else + groupfirst = child->groupnext; + if ( child->groupnext ) + child->groupnext->groupprev = child->groupprev; + kthread_cond_signal(&groupchildleft); + kthread_mutex_unlock(&groupparentlock); + + child->group = NULL; + + NotifyLeftProcessGroup(); +} + +void Process::NotifyLeftProcessGroup() +{ + ScopedLock parentlock(&groupparentlock); + if ( !grouplimbo || groupfirst ) + return; + grouplimbo = false; + delete this; +} + void Process::NotifyChildExit(Process* child, bool zombify) { kthread_mutex_lock(&childlock); @@ -493,22 +500,6 @@ pid_t Process::Wait(pid_t thepid, int* status, int options) if ( zombiechild ) zombiechild->prevsibling = NULL; - // Remove zombie from its process group. - kthread_mutex_lock(&zombie->groupchildlock); - kthread_mutex_lock(&zombie->group->groupparentlock); - assert(zombie->group); - if ( zombie->groupprev ) - zombie->groupprev->groupnext = zombie->groupnext; - else - zombie->group->groupfirst = zombie->groupnext; - if ( zombie->groupnext ) - zombie->groupnext->groupprev = zombie->groupprev; - kthread_cond_signal(&zombie->group->groupchildleft); - kthread_mutex_unlock(&zombie->group->groupparentlock); - zombie->group->NotifyLeftProcessGroup(); - zombie->group = NULL; - kthread_mutex_unlock(&zombie->groupchildlock); - thepid = zombie->pid; // It is safe to access these clocks directly as the child process is no @@ -524,8 +515,13 @@ pid_t Process::Wait(pid_t thepid, int* status, int options) if ( status ) *status = exitstatus; + kthread_mutex_lock(&zombie->groupparentlock); + bool in_limbo = zombie->groupfirst || (zombie->grouplimbo = true); + kthread_mutex_unlock(&zombie->groupparentlock); + // And so, the process was fully deleted. - delete zombie; + if ( !in_limbo ) + delete zombie; return thepid; } @@ -564,6 +560,16 @@ bool Process::DeliverSignal(int signum) return errno = EINIT, false; } +bool Process::DeliverGroupSignal(int signum) +{ + ScopedLock lock(&groupparentlock); + if ( !groupfirst ) + return errno = ESRCH, false; + for ( Process* iter = groupfirst; iter; iter = iter->groupnext ) + iter->DeliverSignal(signum); + return true; +} + void Process::AddChildProcess(Process* child) { ScopedLock mylock(&childlock); diff --git a/sortix/thread.cpp b/sortix/thread.cpp index 58a25420..0deb0186 100644 --- a/sortix/thread.cpp +++ b/sortix/thread.cpp @@ -274,6 +274,9 @@ namespace Sortix // Protect the system idle process. if ( !pid ) { errno = EPERM; return -1; } + // TODO: Implement that pid == -1 means all processes! + bool process_group = pid < 0 ? (pid = -pid, true) : false; + // If we kill our own process, deliver the signal to this thread. Thread* currentthread = CurrentThread(); if ( currentthread->process->pid == pid ) @@ -287,7 +290,9 @@ namespace Sortix // TODO: Check for permission. // TODO: Check for zombies. - return process->DeliverSignal(signum) ? 0 : -1; + return process_group ? + process->DeliverGroupSignal(signum) ? 0 : -1 : + process->DeliverSignal(signum) ? 0 : -1; } int SysRaise(int signum)