views:

1894

answers:

5

Before I begin, I want to clarify that this is not a command-line tool, but an application that accepts commands through it's own command-line interface.

Edit: I must apologize about my explanation from before, apparently I didn't do a very good job at explaining it. One more time...

I am building a command-line interface application that accepts commands from a user. I have a signal handler setup to catch the signals, which then sets a flag that I need to terminate the application. The problem I'm having is all of the console functions I can find are blocking, which means that I can't detect that I need to exit from my console processing loop until the user presses a key (or enter, depending on the function).

Is there some standard way I can do either non-block console interaction, or is there an elegant way to structure the program so that if I just terminate from the signal thread, that everything will be handled and released properly (please don't mis-understand this, I know how this could be done using locking and releasing the resources from the signaling thread, but this could get messy, so I'd rather avoid it)

Hopefully that explanation makes more sense...

A: 

You need to handle the interupt signal. SIGINT on Unix. I'm using an iPod so I can't copy and paste what I found on Google under "sigint handler" for you. But I'm sure someone will help you out shortly.

dlamblin
+1  A: 

In Windows: SetConsoleCtrlHandler

Toji
+2  A: 

On *nix, you can use the signal function to register a signal handler:


#include <signal.h>

void signal_handler(int sig)
{
  // Handle the signal
}

int main(void)
{
  // Register the signal handler for the SIGINT signal (Ctrl+C)
  signal(SIGINT, signal_handler);
  ...
}

Now, whenever someone hits Ctrl+C, your signal handler will be called.

Adam Rosenfield
A: 

On a *nix based system you might not really need a signal handler for this to work. You could specify that you want to ignore the SIGINT call

int main(void)
{
  // Register to ignore the SIGINT signal (Ctrl+C)
  signal(SIGINT, SIG_IGN);

  while(1)
  {
    retval = my_blocking_io_func();
    if(retval == -1 && errno == EINTR)
    {
      // do whatever you want to do in case of interrupt
    }
  }
}

The important way that this works is to recognize that non-blocking functions do get interrupted. Normally, you would realize that the blocking function failed (e.g. read()) and reattempt the function. If it was some other value you would take the appropriate error related action.

terson
+2  A: 

OK - this is working for me on Windows & is portable - notice the #ifdef SIGBREAK - this isn't a standard signal.

#include <csignal>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;

namespace
{
    volatile sig_atomic_t quit;

    void signal_handler(int sig)
    {
        signal(sig, signal_handler);
        quit = 1;
    }
}

int main()
{
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
#ifdef SIGBREAK
    signal(SIGBREAK, signal_handler);
#endif
    /* etc */

    while (!quit)
    {
        string s;
        cin >> s;
        cout << s << endl;
    }
    cout << "quit = " << quit << endl;
}
fizzer