/** * Test a function via a fork function. Tries 5 forks. Kills after ~30 seconds if function has not completed * @param function The function to pass to the test to see if it crashes * @return 1 if successful, 0 if failed */ int fork_test_function(void (*function)()) { const int child_count = 1; int i = 0, j = 0; int jmpres = 0; int result_pid[child_count]; int wstat[child_count]; int fork_test_pid[child_count]; int child_exited_count = 0; // Create the children for(j = 0; j < child_count; j++){ fork_test_pid[j] = fork(); switch(fork_test_pid[j]){ case -1: perror("ERROR AT FORK TESTER\n"); exit(EXIT_FAILURE); break; case 0: for(i = 0; i < 5; i++){ fill_stack_frame(i); jmpres = setjmp(current_test->curjump); if(jmpres != TEST_FAIL){ (function)(); } } exit(EXIT_SUCCESS); break; default: break; } } // Poll the 5 children for 30 seconds, exit the loop if all the children exit for(i = 0; i < 300 && child_exited_count < child_count; i++){ usleep(100); for(j = 0; j < child_count; j++){ result_pid[j] = wait4(fork_test_pid[j], &wstat[j], WNOHANG, (struct rusage *)NULL); if(result_pid[j] != 0) child_exited_count++; } } // Kill off all children unconditionally for(i = 0; i < child_count; i++){ kill(fork_test_pid[i], SIGKILL); } // Check children exit status'. If any one is out of line, return failure (0) for(i = 0; i < child_count; i++){ if(!(result_pid[i] != 0 && WIFEXITED(wstat[i]) > 0 && WEXITSTATUS(wstat[i]) == EXIT_SUCCESS)){ return 0; } } // Return success (1) return 1; }
Process *new_process(void * entry_point, char *name) { Process *p = malloc(sizeof(Process)); p->entry=entry_point; p->regs_page=malloc(4096); p->regs=to_stack_address(p->regs_page); p->regs = fill_stack_frame(entry_point, p->regs); p->state=ACTIVE; p->pid=nextpid; p->name=name; if (nextpid!=0) { p->ppid=current->process->pid; } nextpid++; return p; }