ctrl-c убивает мои фоновые процессы в моей оболочке

Я пытаюсь написать базовую оболочку на C. Одна из вещей, которые мне нужно сделать, - иметь возможность иметь как фоновые, так и передние процессы. Control-C должен убить процесс переднего плана (если он есть) и не должен убивать какие-либо фоновые процессы.

Я написал обработчик сигнала для SIGINT, который убивает процесс переднего плана. Единственная проблема в том, что если у меня есть фоновый процесс, он тоже убивает его. Насколько я понимаю, при нажатии Control-C SIGINT передается по очереди в разные процессы, и если один обрабатывает его, то на этом он останавливается. Моя оболочка должна обрабатывать его, поэтому его нельзя передавать фоновому процессу, верно?

Вот мой код:

pid_t foreground_pid;

int main(int argc, char *argv[]) {
    signal(SIGINT, INThandler);
    char *buf;

    while(1) {
        fgets(buf, 128, stdin);

        */ error checking */
        */ split buf into null terminated char* array (arg_array) 
           and count the number of args (num_args) */

        handlerCommand(buf, arg_array, num_args);

        zombieTerminator();
}

void handleCommand(char *command, char **args, int num) {
    pid_t pid;

    if ((pid = fork()) < 0)
        printf("error\n");
    else if (pid == 0) { // Child
        if (!strcmp(args[num-1], "&")) {
            /* redirect stdin to /dev/null */
        }

        execvp(args[0], args);
        printf("error\n");
        exit(127);
    }

    // parent - either wait (foreground) or continue (background)
    if (!strcmp(args[num-1], "&")) {    
        printf(" [%ld] : %s\n", (long)pid, command);
    } else {
        foreground_pid = pid;
        if ((pid = waitpid(pid, &status, 0)) < 0) 
            fprintf(stderr, "waitpid error\n");
    }

    return;
}

/** Terminates any zombie processes that finished in the background */
void zombieTerminator(void) {
    int status;
    pid_t pid;

    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        if (pid != foreground_pid) {
            printf(" [%ld] exited with status: %d\n", (long)pid, 
                    WEXITSTATUS(status));
        }
    }
}

/** Handles the control-c signal from the keyboard */
void INThandler(int sig) {
    if (foreground_pid) {
        kill(foreground_pid, SIGKILL);
        foreground_pid = 0;
    } else {
        printf("\n%s\? ", cwd);
    }
    fflush(stdout);
}

Когда я запускаю процесс переднего плана:

sleep(100)

Затем я могу нажать contorl-c, и он выйдет. Как и должно. Однако, если я запускаю фоновый процесс:

sleep(100) &

Я получаю новое приглашение, как и должно быть, но если я нажму Control-C, ничего не должно произойти. Но фоновый процесс убивается.

Я хотел бы знать, как остановить фоновый процесс, убиваемый. Есть идеи? :)


person Yep_It's_Me    schedule 15.08.2013    source источник