Родительский процесс не запускается, когда дочерний процесс прерывается с помощью ctrl- \ - PullRequest
1 голос
/ 11 мая 2019

Я делаю это назначение, в котором генерируется несколько дочерних процессов, и если они прерываются (ctrl- \ или ctrl-4), вместо этого должен выполняться родительский процесс. Это код:

int main(int argc, char *argv[])
{

    /* The rest of the code is omitted. "times", "arg1"
    and "cmd1" are parameters passed when running the program */

        for(cont = 0; cont < times; cont++)
        {
                pid = fork();
                if(pid == 0)
                        execvp(arg1,cmd1);
                else if (pid >0) {
                        wait(&status);
                        if (WCOREDUMP(status) !=0)
                                printf("Core dump generado\n");
                }
        }
        return 0;
}

Программа запускает команду Linux несколько раз, при этом argv[1] - это количество раз, arg[2], argv[3] и т. Д. Для самой команды Linux.

Работает нормально, если не отменено. Но когда я пытаюсь прервать его (например, с помощью команды sleep и затем набрать ctrl-4):

./ntimes 2 sleep 10
 ^\Quit (Core dumped)

генерирует дамп. Я хочу, чтобы родительский процесс печатал сообщение вместо этого. Я пробовал с функциями обработки сигналов и многими другими вещами, но я не могу заставить его работать.

1 Ответ

1 голос
/ 11 мая 2019

SIGQUIT нацелен на всю группу процессов переднего плана вашего терминала - он убивает родителя и ребенка. Чтобы предотвратить убийство родителя, вам необходимо:

  1. игнорировать или заблокировать в родительском
  2. поймать его в родительском

При подходе 1. вам нужно разблокировать / игнорировать его у ребенка перед выполнением. С подходом 2. расположение сигнала будет автоматически установлено по умолчанию после его выполнения, поэтому это не повлияет на дочерний процесс, однако наличие хотя бы одного обработчика сигнала откроет ваше приложение до возможности ошибок EINTR при длинных блокирующих системных вызовах, таких как wait, так что вам придется учитывать это.

Вот пример подхода 2. Вы можете попробовать его, например, ./a.out sleep 10 #press Ctrl+\ shortly after this.

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
void h(int Sig){}
int main(int argc, char *argv[])
{
    sigaction(SIGQUIT, &(struct sigaction){.sa_handler=h}, 0);

    int cont, status, times=1;
    pid_t pid;
    for(cont = 0; cont < times; cont++)
    {
        pid = fork();
        if(pid == 0)
            execvp(argv[1],argv+1);
        else if (pid >0) {
            // retry on EINTR
            int rc; do{ rc=wait(&status); }while(0>rc && EINTR==errno);
            if (0>rc) return perror("wait"),1;
            if (WIFSIGNALED(status)){
                if (WCOREDUMP(status))
                    printf("Core dump generado\n");
            }
        }
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...