简体   繁体   中英

how to forward a signal to child process from parent process

I am implementing my own shell, which requests pressing CTRL-Z to suspend foreground process. In order to not suspend my main process but only the child process, I have to catch the SIGTSTP by a handler in my main process and redirect it to my child process(which needed stop). But the kill function never return.

#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>
#include <sys/mman.h>



void handler(){
  pid_t pid;
  int status;
  while((pid = waitpid(-1, &status, 0))>0){
    printf("pid: %d has been reaped\n", pid);
  }
}
  void send_signal(int signum){
     kill(pid, signum);
  }

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


  void start_foreground_job(char** argv)
  {   
    if( (fork()) ==0)
    {   
        signal(SIGTSTP, SIG_DFL);

        if((execve(argv[0], argv, NULL))<0)//envp
        {
            fprintf(stderr, "%s: Command not found.\n", argv[0]);
            exit(0);
         }
     }

     pause();

     return;
 }

  int main(){
    init_signals();
    char* argv[] ={"/bin/sleep", "10", NULL};

    start_foreground_job(argv);

     printf("This line is what I expected after pressing CTRL-Z\n");

    return 0;
  }

When I try your code on my environment, the result is the same with you. I check son process's state after Ctrl+Z,

Before Ctrl + Z

ps -aux | grep sleep
16586  0.0  0.0   2016   412 pts/1    S+   10:42   0:00 /bin/sleep 10

After Ctrl + Z

ps -aux | grep sleep
16586  0.0  0.0   2016   412 pts/1    T+   10:42   0:00 /bin/sleep 10

Son process's state has changed from S -> T. It means father process has sent signal to son process successfully.

But son process doesnot exit, so your waitpid(-1, &status, 0) cannot return.

Option1: send kill signal to son process, and waitpid will get one return.

void send_signal(int signum)
{
    if (pid)
    {
        printf("kill %d, signum %d\n", pid, signum);
        //kill(pid, signum);
        kill(pid, SIGKILL );
    }
}

Option2: waitpid api has one option which can wait for stop state:

void handler()
{
    pid_t pid;
    int status;
    while ((pid = waitpid(-1, &status, WSTOPPED)) > 0) {
        printf("pid: %d has been reaped\n", pid);
        break;
    }
}

Please check below sw version, it works on my workstation.

int pid = 0;
void handler()
{
    pid_t pid;
    int status;
    while ((pid = waitpid(-1, &status, WSTOPPED)) > 0) {
        printf("pid: %d has been reaped\n", pid);
        break;
    }
}
void send_signal(int signum)
{
    if (pid)
    {
        printf("kill %d, signum %d\n", pid, signum);
        kill(pid, signum);
        //kill(pid, SIGKILL );
    }
}

void init_signals()
{
    signal(SIGCHLD, handler);
    signal(SIGTSTP, send_signal);
}


void start_foreground_job(char** argv)
{
    pid = fork();
    if (pid == 0) {
        signal(SIGTSTP, SIG_DFL);

        if ((execve(argv[0], argv, NULL)) < 0) { //envp
            fprintf(stderr, "%s: Command not found.\n", argv[0]);
            exit(0);
        }
    }
    printf("son process pid is %d\n", pid);
    pause();

    return;
}

int main()
{
    init_signals();
    char* argv[] = {"/bin/sleep", "10", NULL};

    start_foreground_job(argv);

    printf("This line is what I expected after pressing CTRL-Z\n");

    return 0;
}

Below is my test result:

./temp
son process pid is 29249
^Zkill 29249, signum 20
pid: 29249 has been reaped
This line is what I expected after pressing CTRL-Z

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