tags:

views:

138

answers:

3

Hi,

I am writing a program that repeatedly does an operation till Ctrl+C is hit by the user in the Linux terminal. I am programming in C. Any ideas how i can implement this.

I have tested my program by using "for" loops with a condition but now i want to make it run as long as Ctrl+C is hit by the user and interrupted.

What I was thinking was of writing a do while loop like the following

do{ /Computation/ } while(Ctrl+C is not hit)

But i dont know how to check for the Ctrl+C input from the user.

Any suggestions will be appreciated.

Thanks

+6  A: 

Ctrl+C will send your program a signal (SIGINT), if you DON'T set up a handler for it will cause your program to exit. So all you have to do is write

do { 
  //computation
} while(1);

and that will do what you want

EDIT: To do what you REALLY wanted without needing a signal handler, and avoiding doing things that might result in the compiler's optimizations breaking your code you can do this:

#include <signal.h>
/* ... */

int main() {
    sigset_t set, oldset;

    sigemptyset(&set);

    /* ... */

    sigaddset(&set, SIGINT);
    sigprocmask(SIG_BLOCK, &set, &oldset);
    do {
        sigset_t pending_set;
        /* ... */
        sigpending(&pending_set);
    } while(!sigismember(&pending_set, SIGINT));
    sigprocmask(SIG_SETMASK, &oldset, NULL);
    /* ... */
}
Spudd86
This will not work if execution is expected to continue after the loop is broken.
You
I tried what you suggested but for some reason the program goes into an infinite loop and does not detect my Ctrl+C. As i understand the program would simply exit however I want to print out a line after it detects a Ctrl+C.Hence it should only get out of this loop, print a line and return after that.
The Stig
Thanks spudd86 for the detailed reply.Appreciate it
The Stig
A: 

When Ctrl-C is hit, a signal is sent to the program. The default behavior is that the program is terminated.

This means that you can let your program run forever, looping endlessly. When the user hits Ctrl-C, the program will abort.

Sjoerd
+11  A: 

A signal trap will do the trick more cleanly than spudd86's suggestion. This example can be improved significantly, though.

#include <signal.h>
/* ... */

int execute;
void trap(int signal){ execute = 0; }

int main() {
    /* ... */
    signal(SIGINT, &trap);
    execute = 1;
    while(execute){
        /* ... */
    }
    signal(SIGINT, SIG_DFL);
    /* ... */
}
You
Can you elaborate on why this way would be preferable?
Larry Wang
If you need to clean up (free memory, save settings, close file handles, things like that) it won't get done when the user interrupts an infinite loop. This way, you are free to continue doing things after the loop is broken. This could be a simple cleanup, or a continuation of the program flow.
You
(Imagine a menu-based program performing heavy calculations; a user could abort the calculation, and with this method you'd be able to send them back to the menu. That's not possible with an infinite loop.)
You
Did you mean to type SIGINT again in the second call to signal()?
Justin K
I did. Fixed now.
You
better solution is to block the signal then use `sigpending()` since that avoids the compiler optimizing this into an infinite loop.
Spudd86
`sigpending()` is a glibc-specific function (and thus not as portable) as far as I can see. But yes, it would be better I suppose.
You
Thanks You for your inputs.I got to learn some basics of signal handling also.
The Stig
This code is broken; a good compiler would optimize that loop to `while(1)`. You need to at least declare `execute` as `volatile`, and you should probably use `sig_atomic_t`.
R..
`sigpending` is part of POSIX. It is not glibc-specific. See http://www.opengroup.org/onlinepubs/9699919799/functions/sigpending.html
R..