Reputation: 5
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
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