Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tristan/safer sighandler #75

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 39 additions & 40 deletions runtime/process-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ typedef struct ChildProcess {
// NOTE: volatile declarations on 'next' forced by compiler.
typedef struct ChildProcessList {
ChildProcess* proc;
volatile struct ChildProcessList * volatile next;
volatile struct ChildProcessList * next;
} ChildProcessList;

// Linked list of live child processes.
// Will be read from by signal handler.
volatile ChildProcessList * volatile child_processes = NULL;
volatile ChildProcessList * child_processes = NULL;

// Add a new ChildProcess to the global 'child_processes' list.
// Precondition: SIGCHLD is blocked
Expand All @@ -47,39 +47,13 @@ void add_child_process (ChildProcess* child) {
// Return the ChildProcess with the given process id.
// Returns NULL if there is none.
static ChildProcess* get_child_process (pid_t pid){
volatile ChildProcessList * volatile curr = child_processes;
volatile ChildProcessList * curr = child_processes;
while(curr != NULL && curr->proc->pid != pid)
curr = curr->next;
if(curr == NULL) return NULL;
else return curr->proc;
}

// Remove the ChildProcess with the given process id from the
// 'child_processes' list if it exists in the list.
// Precondition: SIGCHLD is blocked
static void remove_child_process (pid_t pid) {

// Find the ChildProcess with matching pid.
// After this loop, either:
// 1. curr is NULL: No matching ChildProcess was found.
// 2. curr is ChildProcessList*: The matching ChildProcess was found.
volatile ChildProcessList * volatile curr = child_processes;
volatile ChildProcessList * volatile prev = NULL;
while(curr != NULL && curr->proc->pid != pid) {
prev = curr;
curr = curr->next;
}

// Remove child process from list if one was found.
if(curr != NULL){
if(prev == NULL)
child_processes = curr->next;
else
prev->next = curr->next;
free((void*) curr);
}
}

// After a child process is spawned, this function creates a
// ChildProcess struct for recording the child's metadata
// and stores it in the 'child_processes' list.
Expand Down Expand Up @@ -140,28 +114,46 @@ static void update_child_status (pid_t pid) {
int ret_pid = waitpid(pid, &status, WNOHANG | WUNTRACED | WCONTINUED);

//waitpid returns a positive integer if the process status has changed.
if(ret_pid > 0) {
if(ret_pid > 0)
set_child_status(pid, status);
// Remove the child's metadata from list if child is dead.
if(is_dead_status(status))
remove_child_process(pid);
}
}

// Update the current status of all registered child processes.
// Precondition: SIGCHLD is blocked
static void update_all_child_statuses () {
volatile ChildProcessList * volatile curr = child_processes;
volatile ChildProcessList * curr = child_processes;
while(curr != NULL) {
//NOTE: curr->next is retrieved preemptively because
//update_child_status may call free() on curr, and make
//curr->next inaccessible.
volatile ChildProcessList* next = curr->next;
update_child_status(curr->proc->pid);
curr = next;
curr = curr->next;
}
}

// Remove all ChildProcess nodes that have terminated from the list.
// Precondition: assumes SIGCHLD is blocked
static void remove_dead_child_processes () {
volatile ChildProcessList * curr = child_processes;
volatile ChildProcessList * prev = NULL;
while(curr != NULL) {
// Remove curr if its process has died
if(is_dead_status(*(curr->proc->status))) {
if(prev == NULL) {
child_processes = curr->next;
free((void*) curr);
curr = child_processes;
} else {
prev->next = curr->next;
free((void*) curr);
curr = prev->next;
}
} else {
prev = curr;
curr = curr->next;
}
}
}



//============================================================
//==================== Autoreap Handler ======================
//============================================================
Expand Down Expand Up @@ -326,6 +318,9 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs,
//block sigchld
sigset_t old_signal_mask = block_sigchild();

//cleanup any unneeded process metadata
remove_dead_child_processes();

//Compute which pipes to create for the process.
//has_pipes[PROCESS_IN] = 1, indicates that a process input pipe
//needs to be created.
Expand Down Expand Up @@ -459,6 +454,7 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
stz_int output, stz_int error,
stz_byte* working_dir, stz_byte** env_vars, Process* process) {


//Compute which pipes to create for the process.
//has_pipes[PROCESS_IN] = 1, indicates that a process input pipe
//needs to be created.
Expand Down Expand Up @@ -488,6 +484,9 @@ stz_int launch_process(stz_byte* file, stz_byte** argvs, stz_int input,
//Block SIGCHLD until setup is finished
sigset_t old_signal_mask = block_sigchild();

//cleanup any unneeded process metadata
remove_dead_child_processes();

//Set up the pipes in the parent process.
FILE* fin = NULL;
if(has_pipes[PROCESS_IN]) {
Expand Down