ph0en1x
ph0en1x

Reputation: 5

How do I change the bool variable in the parent process when Ctrl+Z is pressed?

I am trying to implement a custom shell in linux from scratch. In this, I am building two features apart from other basic ones: when user presses ctrl+c, then my custom shell stops executing whatever command it is executing at that moment, and when the user presses ctrl+z, then my custom shell moves the currently executing command to the background.

Here are the bare bones code and implementation details:

//global variable for storing child process id
pid_t child_pid = -1;
//global variable for storing parent process id
pid_t parent_pid = getpid();
//global variable for storing bg flag
bool bg = false;

void sigintHandler(int dummy) {
    kill(child_pid, SIGKILL);
    printf("\n");
}

void sigtstpHandler(int dummy) {
    pid_t present_pid = getpid();
    if(present_pid == parent_pid) {
        bg = true;
    }
}

int main() {

    while (true) {
        signal(SIGINT, sigintHandler);
        signal(SIGTSTP, sigtstpHandler);
        
        cout < ">>";
        //take command from user
         
        child_pid = fork();
        if(child_pid == 0) {
            //code for child process
        }
        else {
            if(!bg)
                wait(&child status);
        }
    }

    return 0;
}

What I am trying to do is that when the user presses ctrl+z, the code should enter the sigtstpHandler function, and if it is in the parent process, change the value of the bg to true so that it stops waiting for the child process to terminate. However, this is not working. Whenever I press Ctrl+Z, the code just hangs apparently or something. Can someone please explain what I am doing wrong? And how to make the parent process stop waiting when ctrl+z is pressed?

Upvotes: 0

Views: 72

Answers (1)

Chris Dodd
Chris Dodd

Reputation: 126243

By default, after the signal handler completes (and returns) the process will go back and 'restart' whatever system call it was doing. So in this case, the parent was in the wait(&child status) call, so it will go back and continue waiting; it will not check the bg flag again.

If you want the signal to interrupt the wait call, you need to use sigaction instead of signal so you can specify the flags, and in particular, do not set the SA_RESTART flag. Then, you also need to check the return value of the wait call, and if it is -1 and errno == EINTR you need to re-check the bg flag and do the right thing.

Upvotes: 1

Related Questions