Kernel: reparent child processes to PID 1 when their parent exits

This commit is contained in:
apio 2022-10-19 17:16:01 +02:00
parent a29f7f8df2
commit 656667812a
2 changed files with 34 additions and 13 deletions

View File

@ -163,24 +163,30 @@ int main()
}
if (child == 0)
{
sleep(2);
sleep(1);
pid_t child = fork();
printf("I am the child (PID %ld), my parent is PID %ld!!\n", getpid(), getppid());
execv("/bin/sym", NULL);
if (child) execv("/bin/sym", NULL);
else
execv("/bin/init", NULL);
perror("execv");
return 1;
}
else { printf("Success!! Got PID %ld\n", child); }
int status;
pid_t result;
while ((result = waitpid(child, &status, 0)) == 0) // Child has not yet exited
for (;;)
{
msleep(100);
pid_t result;
while ((result = wait(&status)) == 0) // No child has exited yet
{
msleep(100);
}
if (result < 0)
{
perror("wait");
return 1;
}
if (WIFEXITED(status)) { printf("Child process %ld exited with code %d\n", result, WEXITSTATUS(status)); }
}
if (result < 0)
{
perror("waitpid");
return 1;
}
if (WIFEXITED(status)) { printf("Child process %ld exited with code %d\n", result, WEXITSTATUS(status)); }
}

View File

@ -45,6 +45,14 @@ template <typename Callback> void sched_for_each_task(Callback callback)
} while (task != base_task);
}
template <typename Callback> void sched_for_each_child(Task* task, Callback callback)
{
sched_for_each_task([&](Task* child) {
if (child->ppid == task->id) { return callback(child); }
return true;
});
}
Task* Scheduler::find_by_pid(uint64_t pid)
{
Task* result = nullptr;
@ -265,6 +273,13 @@ void Scheduler::task_exit(Context* context, int64_t status)
else
sched_current_task->state = sched_current_task->Dying;
sched_current_task->exit_status = status;
if (sched_current_task->id != 1)
{
sched_for_each_child(sched_current_task, [](Task* child) {
if (child->state != child->Exited) child->ppid = 1;
return true;
});
}
task_yield(context);
}
@ -431,8 +446,8 @@ void sys_waitpid(Context* context, long pid, int* wstatus,
Task* child = nullptr;
if (pid == -1)
{
sched_for_each_task([&](Task* task) {
if (task->state == task->Dying && task->ppid == sched_current_task->id)
sched_for_each_child(sched_current_task, [&](Task* task) {
if (task->state == task->Dying)
{
child = task;
return false;