humra
humra

Reputation: 360

Program with loop will not terminate with CTRL + C

I have a program that I want to run until interrupted by user pressing CTRL + C. When I press it nothing happens and I can only terminate the program by suspending it and manually killing it after that.

This is the part of the code that needs to run infinitely:

while(true) {
    liveOrDie(field);
    printOut(field);
}

The first function calculates whether to put 1 or 0 in a two dimensional array and the second one prints it out using a for loop like this:

void printOut(int field[38][102]) {
for(int i = 0; i < 38; i++) {
    for(int j = 0; j < 102; j++) {
        if(field[i][j] == 1) {
            cout << "o";
        }
        else {
            cout << " ";
        }
    }
    cout << endl;
}

system("sleep .1");
}

Sleep is used so there is enough time to print everything out on the screen before it is cleared.

So, program doesn't terminate by Ctrl+C. What may cause this behavior, and how to make the program terminate after Ctrl+C?

Upvotes: 35

Views: 4919

Answers (3)

webuster
webuster

Reputation: 2510

From the documentation of system() (emphasis/bold mine):

The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:

   execl("/bin/sh", "sh", "-c", command, (char *) 0);

system() returns after the command has been completed.

During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored, in the process that calls system() (these signals will be handled according to their defaults inside the child process that executes command).

Which explains your behavior.

Upvotes: 85

rookie coder
rookie coder

Reputation: 141

Have you tried catching the signal? See the example code below:

if (signal (SIGINT, yourFunctionHandler) == SIG_ERR)
    {
        cout << "Error setting the SIGINT handler";
    }

void yourFunctionHandler (int signal)
{
    cout << "Signal " << signal << " received!";
    //do what's needed to kill loop
}

In this way you can modify the loop variable as you wish. And as other people suggested, don't use system().

Signal reference

Small tutorial

Upvotes: 2

Paul R
Paul R

Reputation: 213060

I suspect that the user code runs for some small amount of time, say 1 ms, and the sleep process causes the parent process to block for 100 ms, so unless you're very persistent with the CTRL + C key then the interrupt will most likely be ignored.

You should just replace your call to system("sleep .1") with a proper library call, e.g. change:

system("sleep .1");

to:

usleep(100000);  // NB: requires #include <unistd.h>

See: man usleep.

Upvotes: 61

Related Questions