简体   繁体   中英

How to redirect signal to child process from parent process?

I am trying to understand processes in C. I currently want to create shell-like structure which - after pressing a shortcut like Ctrl + C or Ctrl + Z will kill all its subprocesses but will stay alive. My code looks like this:

#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>

pid_t pid;

void send_signal(int signum){
  kill(pid, signum);
}

void init_signals(){
  signal(SIGINT, send_signal);
  signal(SIGTSTP, send_signal);
}

int main(){
    init_signals();
    pid = fork();
  if(pid > 0){
    //Parent Process
    wait(NULL);
  } else {
    // Child Process
    while(1){
        usleep(300000);
    }   

  }

  return 0;
}

Problem here is that, when I press Ctrl+C, parent redirects it to child and kills it but when I press Ctrl+Z (even though child process is stopped) parent still hangs on wait(NULL) . Any suggestions on how to fix this?

You can check here how to use wait in C . Long story short:

The wait system-call puts the process to sleep and waits for a child-process to end. It then fills in the argument with the exit code of the child-process (if the argument is not NULL).

wait doesn't get signaled until the child process ends, so just by sending the child to sleep there is no reason for the main process to continue. If you want any setup where the main process still works while the child does as well (including when it sleeps!) you can't wait on the child.

Wouldn't make sense for a shell either - it's always active in the background. Instead you need a better handler on main - like waiting on a condition. That way, when sending a child to sleep, you can signal the condition and keep going.

Apart from the solution at https://stackoverflow.com/a/49346549/5694959 I would like to suggest one more solution as to handle signals for parent process only.This way parent will execute signal handler and default action will be performed for child process. Use waitpid() to get the status of child.

waitpid(pid, NULL, WUNTRACED);

Now parent will resume its execution when child process changes its state ie either terminated or stopped.

Update your code as follows:

#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>

pid_t pid;

void send_signal(int signum){
  kill(pid, signum);
}

void init_signals(){
  signal(SIGINT, send_signal);
  signal(SIGTSTP, send_signal);
}

int main(){

    pid = fork();
  if(pid > 0){
    //Parent Process
    init_signals();
    waitpid(pid, NULL, WUNTRACED);
    printf("I think this is what you are expecting...\n");
  } else {
    // Child Process
    while(1){
        usleep(300000);
    }   

  }

  return 0;
}

Just one thing to keep in mind that please make sure that parent process has handled signal before you press ctrl + c or ctrl + z otherwise, default action of signal will be performed for parent as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM