mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Implement sending signals to process groups.
This commit is contained in:
parent
be0ece3fe0
commit
b6349e21cb
3 changed files with 65 additions and 54 deletions
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue