Обработчики сигналов сбрасываются каждый раз - PullRequest
0 голосов
/ 05 января 2019

Я пишу программу на C, которая делает следующее:

Отслеживает, какие сигналы на него отправляются. Подсчитывает, сколько раз были отправлены SIGUSR1 и SIGUSR2. Завершает, когда SIGTERM был отправлен, но сначала печатает, сколько раз были отправлены SIGUSR1 и SIGUSR2.

Пожалуйста, обратите внимание, что это проблема из класса, поэтому она не предназначена для использования, просто чтобы проверить нас. Кроме того, никакие другие сигналы, кроме упомянутых трех, не будут отправлены.

Вот что я получил:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

int sigUsr1Count = 0;
int sigUsr2Count = 0;

static void sighandler(int signum){
    switch(signum){
        case SIGUSR1:
            sigUsr1Count++;
            break;
        case SIGUSR2:
            sigUsr2Count++;
            break;
        case SIGTERM:
            printf("%d %d\n", sigUsr1Count, sigUsr2Count);
            exit(0);
    }
}

int main(int argc, char ** argv){
    pid_t mypid = getpid();
    fprintf(stderr, "My PID is %d\n", mypid);

    struct sigaction sa;
    sa.sa_flags = 0; 
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = sighandler;
    iAssert(-1 != sigaction(SIGUSR1, &sa, NULL), "sigaction1 failed");
    iAssert(-1 != sigaction(SIGUSR2, &sa, NULL), "sigaction1 failed");
    iAssert(-1 != sigaction(SIGTERM, &sa, NULL), "sigaction1 failed");

    while(true){
        fprintf(stderr, "Waiting...\n");
        sleep(3);
    }

    return 0;
}

Я где-то читал на форуме, что при использовании sigaction обработчики сигналов НЕ сбрасываются в значения по умолчанию, если в поле sa_flags не установлено значение SA_RESETHAND. Тем не менее, это не так со мной. (Страница man описывает флаг SA_RESETHAND, но не содержит явных сведений о действии в ситуации, когда он опущен.)

Когда я запускаю программу, она переходит к моим обработчикам только при первой отправке SIGUSR1 или SIGUSR2, после чего программа завершает работу с сообщением:

User defined signal 1 (or 2)

В этом смысле программа выводит правильные значения только в том случае, если либо: SIGUSR1 и SIGUSR2 не были отправлены вообще, либо каждое из них было отправлено не более одного раза.

Макрос и функция iAssert:

#define iAssert(cond, msg) crash(cond, msg, __LINE__)
void crash(bool cond, char * msg, int line){
    if(!cond){
        perror(msg);
        fprintf(stderr, "at line %d\n", line);
        exit(EXIT_FAILURE);
    }
}

Методы компиляции, которые я уже пробовал (одинаковые с каждым из них):

gcc 1.c
gcc -std=c99 1.c
gcc -std=c11 1.c

Есть идеи?

Спасибо.

1 Ответ

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

Ну, так как все комментарии оказались одинаково бесполезными (без обид), я решил использовать другой подход.

Вместо sigaction я использовал системный вызов signal. Я также изменил несколько других вещей. Поскольку printf не является сигнальной функцией, я ввел глобальную переменную с именем shouldStop, которая по умолчанию установлена ​​на false, а затем изменена на true с помощью обработчика SIGTERM. Печать выполняется внутри функции main.

Вот код:

int sigUsr1Count = 0;
int sigUsr2Count = 0;

bool shouldStop = false;

static void sighandler(int signum){
    switch(signum){
        case SIGUSR1:
            sigUsr1Count++;
            break;
        case SIGUSR2:
            sigUsr2Count++;
            break;
    }
}

static void termhandler(int signum){
    shouldStop = true;
}

int main(int argc, char ** argv){
    pid_t mypid = getpid();
    fprintf(stderr, "My PID is %d\n", mypid);

    iAssert(SIG_ERR != signal(SIGUSR1, sighandler), "signal1 failed");
    iAssert(SIG_ERR != signal(SIGUSR2, sighandler), "signal2 failed");
    iAssert(SIG_ERR != signal(SIGTERM, termhandler), "signal3 failed");

    do{

    }while(!shouldStop);
    printf("%d %d\n", sigUsr1Count, sigUsr2Count);

    return 0;
}   

И он работает так, как я хотел.

В любом случае, спасибо.

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