Killing разветвленный дочерний процесс убивает родителя в обработчике SIGCHLD - PullRequest
0 голосов
/ 20 января 2019

Я пишу простую оболочку на C, которая поддерживает выполнение обычных команд Linux, а также пару встроенных команд, которые я написал сам (например, «выход» для выхода из оболочки).Оболочка создает новый дочерний элемент для каждой введенной команды.У меня есть обработчик SIGCHLD, который получает детей-зомби, когда дочерний процесс завершается.Моя проблема заключается в том, что всякий раз, когда я запускаю фоновый процесс, родитель (сама программа-оболочка) также уничтожается при вызове обработчика SIGCHLD.

Я уже посмотрел в этом посте и сделалнебольшой обработчик SIGPIPE, но он никогда не вызывается, поэтому я не думаю, что это проблема.

Эта eval функция обрабатывает каждую введенную команду и решает, запускать ли ее на переднем плане или в фоне:

void eval(char *cmdline) 
{
    char *argv[MAXARGS];
    char buf[MAXLINE];
    int bg;
    pid_t pid;
    sigset_t mask_all, mask_one, prev_one;

    sigfillset(&mask_all);
    sigemptyset(&mask_one);
    sigaddset(&mask_one, SIGCHLD);


    strcpy(buf, cmdline);
    /* Is it a background command (ends in &) ? */
    bg = parseline(buf, argv);

    /*Ignore empty lines */
    if(argv[0] == NULL)
        return;

    /*builtin_cmd just handles my own custom commands */
    if(!builtin_cmd(argv)) {

        /*Block SIGCHLD signals */
        sigprocmask(SIG_BLOCK, &mask_one, &prev_one);
        if((pid = fork()) == 0) {
            /* Unblock SIGCHLD */
            sigprocmask(SIG_SETMASK, &prev_one, NULL);
            if(execve(argv[0], argv, environ) < 0) {
                fprintf(stderr, "%s: Command not found\n", argv[0]);
                fflush(stderr);
                exit(0);
            }
        }

        /* Block all signals */
        sigprocmask(SIG_BLOCK, &mask_all, NULL);
        setpgid(pid, 0);
        if(!bg) {
            /*Wait for foreground job to complete */
            int status;
            if(waitpid(pid, &status, 0) < 0) {
                fprintf(stderr, "wait pid error");
            }
        } else {
            /* Add the job to the jobs array */
            /* BG just means it's in the background */
            addjob(jobs, pid, BG, cmdline);
            int jid = (*getjobpid(jobs, pid)).jid;
            printf("[%d] (%d) %s", jid, pid, cmdline);
        }
        /*Unblock signals */
        sigprocmask(SIG_SETMASK, &prev_one, NULL);
    }

    return;
}

Вот мой обработчик SIGCHLD:

void sigchld_handler(int sig) 
{
    int olderrno = errno;
    sigset_t mask_all, prev_all;
    sigfillset(&mask_all);

    /*Reap zombie */
    pid_t pid;
    if((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
        sigprocmask(SIG_BLOCK, &mask_all, &prev_all);   //Block all signals
        deletejob(jobs, pid);                           //Delete job from jobs array
        sigprocmask(SIG_SETMASK, &prev_all, NULL);      //Unblock signals
    }

    //WHY DOES THIS EXECUTE FOR BACKGROUND JOBS???
    if(errno != ECHILD) {
        printf("waitpid error");
    }
    errno = olderrno;

    return;
}

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

brett@brett-linux:~/Desktop/Shell$ ./tsh
tsh> /bin/sleep 1 &
[1] (7223) /bin/sleep 1 &
tsh> waitpid error
brett@brett-linux:~/Desktop/Shell$

Как видите, программа просто умирает.Почему это происходит?

1 Ответ

0 голосов
/ 20 января 2019

Удаление небезопасной безопасной функции printf устраняет проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...