【问题标题】:How to catch SIGINT and ignore it in the child process?如何在子进程中捕获 SIGINT 并忽略它?
【发布时间】:2014-02-26 02:32:32
【问题描述】:

我有一个从命令行参数运行程序的主程序。命令行程序被分叉并在子进程中运行。当发送 SIGINT 时,我想抓住它并要求用户确认他/她要退出。如果是,则父母和孩子都结束,否则孩子继续运行。 我的问题是,当用户拒绝时,我无法让孩子重新开始跑步。 我试过 SIGSTOP & SIGCONT 但这些实际上只是导致进程停止。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

extern char **environ;
void sigint_handler(int sig);
void sigint_chldhandler(int sig);

int main( int argc, char** argv)
{
    int pid;
    signal(SIGINT,sigint_handler);


    if((pid=fork())==0)
    {
            printf("%d\n",pid);

            execve(argv[1],argv,environ);
    }


    int status;
    waitpid(pid,&status,0);
}
void sigint_handler(int sig)
{
    printf("Do you want to quit?Yes/No:\n");
    char buf[4];
    fgets(buf, sizeof(char)*4, stdin);

    printf("child pid:%d\n",getpid());
    printf("parent pid:%d\n",getppid());

    if(strcmp(buf,"Yes")==0)
    {
            kill(-getpid(),SIGKILL);
            printf("Exiting!\n");
            exit(0);
    }

}

【问题讨论】:

  • 我认为你也可以在子进程中使用signal(SIGINT, SIG_IGN);,或者为它编写另一个SIGINT处理程序。
  • 否,如果我阻止 sigint,那么当用户按下 ctrl C 时,无限子进程永远不会停止。我想发送 cntl C sig 并要求用户确认他是否真的想退出,如果用户说不,然后子进程继续
  • 您可以阻止子进程退出父进程。你有一个孩子的pid。 SIGINT 来到父进程和子进程。父进程调用您的处理程序。 Child 默认处理这个信号。这是你的问题。

标签: c signals systems-programming


【解决方案1】:

除非您操纵子级的信号处理,否则无论父级发生什么,它都会在发送信号时被中断终止。因此,您将需要更加复杂。我认为您将需要以下内容:

  1. 父进程设置其 SIGINT 信号处理程序。
  2. 父分叉。
  3. 子进程将其 SIGINT 处理设置为 SIG_IGN。
  4. 子执行指定的命令。
  5. 父母等待 SIGINT 到达,可能在运行 waitpid() 时。
  6. 当它到达时,它会向孩子发送 SIGSTOP。
  7. 它提出问题并得到响应。
  8. 如果要继续响应,则向子节点发送 SIGCONT 并返回其等待模式。
  9. 如果响应要停止,则它首先发送 SIGCONT,然后发送 SIGTERM(或除 SIGINT 之外的其他信号)给子进程以杀死它。 (使用 SIGKILL 是不明智的;应该让孩子有机会退出以响应 SIGTERM 或 SIGHUP。如果孩子没有认真对待死亡威胁,那么您可以发送 SIGKILL。)
  10. 当父母确定孩子已经退出时,它可以自己退出。

请注意,如果子进程正在运行类似vim 的东西,这会极大地改变终端设置,那么发送它 SIGKILL 将使终端处于翘起状态。它巧妙地把它恢复到理智的状态。最好让程序有机会自行重置终端设置。

【讨论】:

    【解决方案2】:

    SIGINT 到达父进程和子进程(到进程组)。
    父进程调用您的处理程序。
    Child 默认处理这个信号。
    您可以使用它,例如:

    #include <unistd.h>
    #include <signal.h>
    #include <stdio.h>
    int main()
    {
        pid_t pid;
        char c;
        switch(pid = fork())
        {
            case -1:
                printf("!!!");
                return -1;
            break;
            case 0:
                printf("child started\n");
                while(1) { };
            break;
            default:
                while(1)
                {
                    c = getchar();
                    if(c == 'q')
                    {       
                            //your conditions
                            kill(pid, SIGKILL);
                            return 0;
                    }
                }
            break;
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-17
      • 1970-01-01
      • 2012-10-08
      • 1970-01-01
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      相关资源
      最近更新 更多