Использование sigaction без SA_RESTART и предотвращение бесконечного цикла - PullRequest
0 голосов
/ 04 мая 2020

У меня есть следующий код:

struct sigaction act = {{0}};
act.sa_handler = handler;
sigaction(SIGINT, &act, nullptr);
while (true) 
{
    std::cout << "input:";
    std::getline(std::cin, line);
    // Handle line
}

Когда я получаю SIGINT, программа застревает в бесконечном l oop. Я не могу просто установить SA_RESTART (например, здесь ), потому что я хочу напечатать сообщение, когда получу сигнал.

Я не хочу печатать напрямую из обработчика, поэтому я установите в нем флаг и отметьте его в l oop.

if (flag)
    std::count << "got SIGINT" << std::endl;

SA_RESTART заставляет getline блокировать, поэтому я не могу достичь этого if и обработать сигнал, если getline не вернет. Есть ли что-нибудь вокруг этого?

edit (полный пример):

#include <iostream>
#include <signal.h>

bool flag = false;

void handler(int signum)
{
    flag = true;
}

int main()
{

    struct sigaction act = {{0}};
    act.sa_handler = handler;
    //act.sa_flags = SA_RESTART;
    sigaction(SIGINT, &act, nullptr);
    while (true) 
    {
        std::cout << "input:";
        std::string line;
        std::getline(std::cin, line);

        if (flag) {
           std::cout << "got SIGINT" << std::endl;
           flag = false;
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 04 мая 2020

Когда getline прерван, флаг ошибки будет установлен на cin. Это необходимо очистить, чтобы предотвратить постоянный сбой getline.

if (flag) {
   std::cout << "got SIGINT" << std::endl;
   flag = false;
   std::cin.clear();
}
0 голосов
/ 04 мая 2020

bool flag = false; неверно, когда flag устанавливается обработчиком сигнала.

Правильно:

std::sig_atomic_t volatile flag = false;

Подробнее см. std::sig_atomic_t подробности.

...