如何捕获SIGINT并在子进程中忽略它?

时间:2014-02-26 02:32:33

标签: c signals systems-programming

我有一个从命令行参数运行程序的main。命令行程序在子进程中分叉并运行。当发送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);
    }

}

2 个答案:

答案 0 :(得分:1)

除非您操纵孩子的信号处理,否则无论父母发生什么事情,它都会在发送信号时被中断终止。因此,您需要更加复杂。我想你需要的东西是:

  1. 父进程设置其SIGINT信号处理程序。
  2. 父叉。
  3. 子进程将其SIGINT处理设置为SIG_IGN。
  4. Child执行指定的命令。
  5. Parent可能在运行waitpid()时等待SIGINT到达。
  6. 当它到达时,它会向孩子发送SIGSTOP。
  7. 它询问问题并得到答复。
  8. 如果要继续响应,则会将SIGCONT发送给子进程并返回其等待模式。
  9. 如果响应停止,则它首先发送SIGCONT,然后发送SIGTERM(或除SIGINT之外的其他信号)以杀死它。 (使用SIGKILL是不明智的;孩子应该有机会退出以响应SIGTERM或SIGHUP。如果孩子没有认真对待死亡威胁,那么你可以发送SIGKILL。)
  10. 当父母确定孩子已退出时,它可以自行退出。
  11. 请注意,如果子进程正在运行类似vim的内容,这会极大地改变终端设置,那么发送SIGKILL将使终端处于cockeyed状态。它将它恢复到一个理智的状态;最好让程序有机会自行重置终端设置。

答案 1 :(得分:0)

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