#include #include #include #include struct node { pid_t pid; struct node *next; }; static struct node * add_node(pid_t pid, struct node *n) { struct node *n2 = malloc(sizeof(struct node)); n2->pid = pid; n2->next = n; return n2; } static struct node * remove_node(pid_t pid, struct node *n) { if (!n) { return n; } else if (n->pid == pid) { struct node *n2 = n->next; free(n); return remove_node(pid, n2); } else { n->next = remove_node(pid, n->next); return n; } } extern void track_process(int fd, pid_t pid, int b) { unsigned int buffer[2]; //printf("Tracking process %d, %d\n", pid, b); buffer[0] = pid; buffer[1] = b; if (! write(fd, buffer, sizeof(unsigned int) * 2)) { //printf("Error writing to fd %d\n", fd); } } // Returns FD to write to, or -1 on failure. extern int launch_process_tracker(void) { int pipes[2]; pid_t child; if (pipe(pipes)) { return -1; } child = fork(); if (child < 0) { return -1; } else if (child == 0) { unsigned int buffer[2]; struct node *n = 0, *n2; close(pipes[1]); // Prevent monitoring programs like Upstart from killing this // new process along with the parent setpgid(0, 0); while (read(pipes[0], buffer, sizeof(unsigned int) * 2) > 0) { if (buffer[1]) { //printf("Adding node %d\n", buffer[0]); n = add_node(buffer[0], n); } else { //printf("Removing node %d\n", buffer[0]); n = remove_node(buffer[0], n); } } for (n2 = n; n2; n2 = n2->next) { //printf("Sending process %d TERM signal\n", n2->pid); kill(n2->pid, SIGTERM); } sleep(2); while (n) { //printf("Sending process %d KILL signal\n", n->pid); kill(n2->pid, SIGKILL); n2 = n; n = n->next; free(n2); } exit(0); } else { close(pipes[0]); return pipes[1]; } }