简体   繁体   中英

Using Signal Handlers to Pause/Resume a Child Process

I'm currently trying to experiment with signals in C by using them to control a child process created with the fork() method. Essentially, I have a child process running the "yes" command from the linux terminal (this command just prints "y" and a newline until it is terminated). I want to be able to pause/resume this process with CTRL-Z. This is what i've got right now:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
pid_t CHILD_PROCESS;
pid_t PARENT_PROCESS;
int isPaused;
void pause_handler(int signo){
  if(!isPaused){  
    printf("Ctrl-Z pressed. Pausing child.\n");
    isPaused = 1;
    kill(CHILD_PROCESS,SIGSTOP);
  }
  else if(isPaused){
   printf("\nCtrl-Z pressed. Resuming child.\n");
   kill(CHILD_PROCESS,SIGCONT);
   isPaused = 0;
  }
}

int main(int argc, char** argv){
  pid_t pid;
  PARENT_PROCESS = getpid();
  pid = fork();
  if(pid == 0){
    system("yes");
  }
  isPaused = 0;
  if(pid > 0){
    signal(SIGTSTP, SIG_IGN);
    signal(SIGSTOP, SIG_IGN);
    CHILD_PROCESS = pid;
    while(1){
      if(signal(SIGTSTP,pause_handler) == SIG_ERR){
        printf("Signal Failure");
      }
    }
  }
}

When I run this, I can get "Ctrl-Z pressed. Pausing child." to print to console by pressing CTRL-Z, and I can get "Ctrl-Z pressed. Resuming child." to print to the console by pressing CTRL-Z again. However, it doesn't actually resume printing "y" over and over again. Any ideas as to why the child process isn't resuming?

As it turns out, system has an implicit fork call within it, so the PID that gets stored in CHILD_PROCESS ends up not actually being the child process, and instead an intermediate one.

From man 3 system :

   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.

So, if we replace the system("yes") call with execl("/bin/sh", "sh", "-c", "yes", NULL) , then we avoid this extra fork and the program functions as desired.


The only other issue is that, by I comment I found on this post , using printf within a signal handler is undefined behavior. Not an issue to worry about here, but something to keep in mind for future code!

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