как переслать сигнал дочернему процессу из родительского процесса - PullRequest
0 голосов
/ 22 апреля 2020

Я реализую свою собственную оболочку, которая запрашивает нажатие CTRL-Z для приостановки процесса переднего плана. Чтобы не приостанавливать мой основной процесс, а только дочерний процесс, я должен перехватить SIGTSTP с помощью обработчика в моем основном процессе и перенаправить его на мой дочерний процесс (который необходимо остановить). Но функция kill никогда не вернется.

#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;
  }

1 Ответ

0 голосов
/ 22 апреля 2020

Когда я пробую ваш код в моей среде, результат у вас тот же. Я проверяю состояние процесса сына после Ctrl + Z ,

До Ctrl + Z

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

После Ctrl + Z

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

Состояние процесса сына изменилось с S - > T. Это означает, что родительский процесс успешно отправил сигнал дочернему процессу.

Но дочерний процесс не завершается, поэтому ваш waitpid (-1, & status, 0) не может вернуться.

Option1: send сигнал kill для процесса son, и waitpid получит одно возвращение.

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

Option2: API-интерфейс waitpid имеет одну опцию, которая может ожидать состояние остановки:

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

Пожалуйста, проверьте ниже версию sw , он работает на моей рабочей станции.

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;
}

Ниже приведен мой результат теста:

./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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...