I'm making a shell in C and I need to be able to handle SIGINT and SIGTSTP signals so as the shell doesn't terminate but it passes the signals to the child processes. I've found various posts here saying I should either use kill(child_pid,SIGINT) in the signal handler with child_pid being the id fork() returns, or to use killpg() while setting a new groupid to the child process before it uses execvp(). None of these work for me, as the handler only displays what I've put in it using the write() function, but doesn't terminate the child.
// global variable
__pid_t child_pid = 0;
int main(){
// init variables
pid_t childpid;
char *commandp;
while(1){
ignore();
//do stuff that read input
// do stuff that end up using fork to make child process
if ( ( childpid = fork() ) == -1 ){
perror ( " Fork fail " );
exit (2); // exit value 2 means fork fail inside the shell
}
if (childpid == 0){
setpg(getpid(), getpid());
child_pid = getpgrp();
commandp = argv[0];
execvp(commandp, argv);
}
else {
ignore_child();
waitpid(childpid, &status, WUNTRACED);
}
}
}
//signal handling functions
void ignore(){
struct sigaction act;
act.sa_handler=SIG_IGN;
// sigaction()
sigaction(SIGINT, &act, NULL);
sigaction(SIGTSTP, &act, NULL);
}
void ignore_child(){
struct sigaction act;
act.sa_handler = &handle_signal;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTSTP, &act, NULL);
}
void handle_signal(int sig){
if (child_pid != 0)
if (sig == SIGINT){
write(STDERR_FILENO, "Received SIGINT (CTRL-C) signal. Exiting...\n", 46);
killpg(child_pid, SIGINT);
}
else if (sig == SIGTSTP){
write(STDERR_FILENO, "\nReceived SIGSTP (CTRL-Z) signal. Stopping...\n", 47);
killpg(child_pid, SIGTSTP);
}
}
Any idea why the child process doesn't terminate but the message from the signal handler displays fine?