1

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;
        }
    }
}
shroz
  • 13
  • 5
  • 2
    Can you please provide a [minimal verifiable example](https://stackoverflow.com/help/minimal-reproducible-example). That is, code that someone else can copy and run to reproduce the problem? – kaylum May 04 '20 at 06:36
  • volatile bool flag = false; – Erki Aring May 04 '20 at 07:32
  • 1
    @ErkiAring This doesn't work. The problem is that getline doesn't block on the next call after getting interrupted by the signal. – shroz May 04 '20 at 07:51
  • 1
    Please don't add the C tag back. C and C++ are different languages and the answer will be different for each. The problem may exist in both as you commented but it does not mean the solution will be the same. – kaylum May 04 '20 at 08:04

2 Answers2

2

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();
}
kaylum
  • 13,833
  • 2
  • 22
  • 31
0

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.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271