shroz
shroz

Reputation: 13

Using sigaction without SA_RESTART and preventing an infinte loop

I have the following code:

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

When I receive SIGINT, the program gets stuck in an infinite loop. I can't simply set SA_RESTART (like here) because I want to print a message when I receive the signal.

I don't want to print directly from the handler, so I set a flag in it and check it in the loop.

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

SA_RESTART causes getline to block, so I can't reach this if and handle the signal unless getline returns. Is there anyway around this?

edit(full example):

#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;
        }
    }
}

Upvotes: 1

Views: 1654

Answers (2)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136365

bool flag = false; is not correct when flag is being set by a signal handler.

Correct:

std::sig_atomic_t volatile flag = false;

See std::sig_atomic_t for more details.

Upvotes: 0

kaylum
kaylum

Reputation: 14046

When getline is interrupted an error flag will be set on cin. That needs to be cleared to prevent getline from continuously failing.

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

Upvotes: 3

Related Questions