C программа - процесс не вызывается после отправки сигнала SIGTERM - PullRequest
2 голосов
/ 09 января 2020

Я новичок в использовании сигналов при C программировании.

Я написал два простых исходных кода: дочерний. c и родительский. c, чтобы продемонстрировать мою проблему.

child. c

void errorHandler(char* message);
void sigterm_handler(int signum, siginfo_t* info, void* ptr);

int main(){

    struct sigaction action1;
    memset(&action1, 0, sizeof(action1));
    action1.sa_sigaction = sigterm_handler;
    action1.sa_flags = SA_SIGINFO;

    if(sigaction(SIGTERM, &action1, NULL) != 0)
        errorHandler("Signal sigterm_handler registration failed");

    for(int i = 0; i < 10; i++){

        printf("%d\n", i);
        if(i == 5){

            if(raise(SIGSTOP)!= 0)
                errorHandler("Raise SIGSTOP failed");
        }
    }

    return EXIT_SUCCESS;
}

void errorHandler(char* message){

    printf("Error: %s: %s\n", message, strerror(errno));
    exit(EXIT_FAILURE);
}

void sigterm_handler(int signum, siginfo_t* info, void* ptr){

    printf("Child: Process %d finishes\n", getpid());
    exit(EXIT_SUCCESS);
}

parent. c

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

    int status;
    pid_t mem;
    pid_t child = fork();

    if(child == 0){

        char* arr[] = {"./child", NULL};
        execv(arr[0], arr);
    }

    else if(child > 0){

        mem = child;
        waitpid(mem, &status, WUNTRACED);
    }

    if(WSTOPSIG(status)){

        printf("Sending SIGTERM to child\n");
        kill(mem, SIGTERM);
        waitpid(mem, &status, 0);
    }

    return 0;
}

Когда я запускаю parent. c, программа печатает в стандартный вывод:

1
2
3
4
5
Sending SIGTERM to child

но затем программа застревает, вероятно, из-за того, что sigterm_handler не вызывается, вместо вывода «Child: Process *** заканчивается».

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

Может кто-нибудь объяснить мне, что является причиной этой проблемы?

Любой ответ был бы признателен!

1 Ответ

2 голосов
/ 09 января 2020

Проблема в том, что дочерний процесс, который вызывает

if(raise(SIGSTOP) != 0)

, все еще остановлен , когда родительский элемент

kill(mem, SIGTERM);

отправляет сигнал SIGTERM. Сигнал не теряется, но все еще ожидает обработки дочернего процесса и будет доставлен, как только процесс продолжится. Вы можете добиться этого, выдав

kill(mem, SIGCONT);

непосредственно после отправки SIGTERM. Затем ребенок возобновит работу, сигнал будет доставлен, и обработчик будет выполнен, распечатав сообщение о диагностике c и выйдя из процесса.

...