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
|
class Process
|
||||||
{
|
{
|
||||||
friend void Process__OnLastThreadExit(void*);
|
friend void Process__OnLastThreadExit(void*);
|
||||||
friend void Process__LastPrayerFinalize(void*);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Process();
|
Process();
|
||||||
|
@ -177,6 +176,7 @@ public:
|
||||||
void Exit(int status);
|
void Exit(int status);
|
||||||
pid_t Wait(pid_t pid, int* status, int options);
|
pid_t Wait(pid_t pid, int* status, int options);
|
||||||
bool DeliverSignal(int signum);
|
bool DeliverSignal(int signum);
|
||||||
|
bool DeliverGroupSignal(int signum);
|
||||||
void OnThreadDestruction(Thread* thread);
|
void OnThreadDestruction(Thread* thread);
|
||||||
int GetParentProcessId();
|
int GetParentProcessId();
|
||||||
void AddChildProcess(Process* child);
|
void AddChildProcess(Process* child);
|
||||||
|
@ -192,7 +192,7 @@ private:
|
||||||
CPU::InterruptRegisters* regs);
|
CPU::InterruptRegisters* regs);
|
||||||
void OnLastThreadExit();
|
void OnLastThreadExit();
|
||||||
void LastPrayer();
|
void LastPrayer();
|
||||||
void LastPrayerFinalize();
|
void NotifyMemberExit(Process* child);
|
||||||
void NotifyChildExit(Process* child, bool zombify);
|
void NotifyChildExit(Process* child, bool zombify);
|
||||||
void NotifyNewZombies();
|
void NotifyNewZombies();
|
||||||
void DeleteTimers();
|
void DeleteTimers();
|
||||||
|
|
|
@ -341,41 +341,14 @@ void Process::LastPrayer()
|
||||||
|
|
||||||
iszombie = true;
|
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;
|
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
|
// This class instance will be destroyed by our parent process when it
|
||||||
// has received and acknowledged our death.
|
// has received and acknowledged our death.
|
||||||
kthread_mutex_lock(&parentlock);
|
kthread_mutex_lock(&parentlock);
|
||||||
|
@ -385,7 +358,14 @@ void Process::LastPrayerFinalize()
|
||||||
|
|
||||||
// If nobody is waiting for us, then simply commit suicide.
|
// If nobody is waiting for us, then simply commit suicide.
|
||||||
if ( !zombify )
|
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()
|
void Process::ResetAddressSpace()
|
||||||
|
@ -403,6 +383,33 @@ void Process::ResetAddressSpace()
|
||||||
segments = NULL;
|
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)
|
void Process::NotifyChildExit(Process* child, bool zombify)
|
||||||
{
|
{
|
||||||
kthread_mutex_lock(&childlock);
|
kthread_mutex_lock(&childlock);
|
||||||
|
@ -493,22 +500,6 @@ pid_t Process::Wait(pid_t thepid, int* status, int options)
|
||||||
if ( zombiechild )
|
if ( zombiechild )
|
||||||
zombiechild->prevsibling = NULL;
|
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;
|
thepid = zombie->pid;
|
||||||
|
|
||||||
// It is safe to access these clocks directly as the child process is no
|
// 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 )
|
if ( status )
|
||||||
*status = exitstatus;
|
*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.
|
// And so, the process was fully deleted.
|
||||||
delete zombie;
|
if ( !in_limbo )
|
||||||
|
delete zombie;
|
||||||
|
|
||||||
return thepid;
|
return thepid;
|
||||||
}
|
}
|
||||||
|
@ -564,6 +560,16 @@ bool Process::DeliverSignal(int signum)
|
||||||
return errno = EINIT, false;
|
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)
|
void Process::AddChildProcess(Process* child)
|
||||||
{
|
{
|
||||||
ScopedLock mylock(&childlock);
|
ScopedLock mylock(&childlock);
|
||||||
|
|
|
@ -274,6 +274,9 @@ namespace Sortix
|
||||||
// Protect the system idle process.
|
// Protect the system idle process.
|
||||||
if ( !pid ) { errno = EPERM; return -1; }
|
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.
|
// If we kill our own process, deliver the signal to this thread.
|
||||||
Thread* currentthread = CurrentThread();
|
Thread* currentthread = CurrentThread();
|
||||||
if ( currentthread->process->pid == pid )
|
if ( currentthread->process->pid == pid )
|
||||||
|
@ -287,7 +290,9 @@ namespace Sortix
|
||||||
// TODO: Check for permission.
|
// TODO: Check for permission.
|
||||||
// TODO: Check for zombies.
|
// 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)
|
int SysRaise(int signum)
|
||||||
|
|
Loading…
Add table
Reference in a new issue