2014-05-05 20 views
1

我与UNIX系统下测试C程序调用:SIGINT只在孩子的过程中接收,如果抓明确

#include <unistd.h> 
#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void abide(int sig_num) { 
    printf("I, sleeper, will abide to this signal %d!\n", sig_num); 
    fflush(stdout); 
    exit(0); 
} 

void refuse(int sig_num) { 
    signal(SIGINT, refuse); 
    printf("I, sleeper, REFUSE this signal %d!\n", sig_num); 
    fflush(stdout); 
} 

int main(int argc, char *argv[]) { 
    if (argc > 1 && strcmp(argv[1], "refuse") == 0) { 
     signal(SIGINT, refuse); 
    } else if (argc > 1 && strcmp(argv[1], "deaf") == 0) { 
     printf("I, sleeper, have been made deaf...\n"); 
    } else { 
     signal(SIGINT, abide); 
    } 
    printf("I, sleeper, am now sleeping for 10s...\n"); 
    sleep(10); 
    printf("I, sleeper, has terminated normally.\n"); 
    return 0; 
} 

然后我有另一个程序,如同一个小的壳。在我的测试点上,它会分叉并使子程序执行上面的程序(使用适当的参数)。这个外壳也忽略Ctrl + C键通过使用

signal(SIGINT, SIG_IGN); 

结果命令如下:

MyShell> ./sleeper 
I, sleeper, am now sleeping for 10s... 
^CI, sleeper, will abide to this signal! 
MyShell> ./sleeper refuse 
I, sleeper, am now sleeping for 10s... 
^CI, sleeper, REFUSE this signal! 
I, sleeper, has terminated normally. 
MyShell> ./sleeper deaf 
I, sleeper, have been made deaf... 
I, sleeper, am now sleeping for 10s... 
^C^C^C^C <---- not terminating 

第一次运行似乎是正确的。第二个有点奇怪,因为我们实际上忽略了信号,但程序终止。也许是因为我们打电话sleep()这被打断了。

但这是第三个让我困惑的结果。在一个普通的shell程序终止,但在我的自定义shell中没有任何反应。它继续运行。睡眠者程序的默认信号处理程序(终止它)是否应该像abide()一样执行?

感谢您的任何澄清!

+1

预计第一次运行的输出是?你的'abide'函数调用'exit()',但是你仍然看到'main'的最后一个'printf'输出? –

+0

我的不好。我错误地复制了输出。我编辑了这篇文章。 – bombax

+0

你似乎刚刚编辑出来,这导致我认为你给我们展示的不是*真实*控制台输出... –

回答

1

解决了它。问题有点微妙。在使用fork()后,子进程显然会继承其父节点的信号处理程序,即使您之后使用了系统调用exec()。所以sleeper的子进程正在使用忽略处理程序。解决的办法是简单地

signal(SIGINT, SIG_DFL)

调用之间

添加默认的处理程序fork()exec()

+2

这对我来说没有意义。儿童不会通过'exec'继承信号处理程序。在'exec'之后,原始文本段(即包含处理程序的代码)被汽化,那么继承了什么?处理程序的地址指向什么?取而代之的是,'exec'在将处理程序重置为其默认处置的任何信号后,OS执行的操作。所以我想我不明白你的问题或解决方案。你要留下什么吗? – Duck

+0

据我所知不是。如果我在调用exec之前明确地将信号处理程序重置为默认值,而不是如果我不这样做,它会按预期工作。我按照'uname'运行Linux 3.2.0-61-generic。我特别使用'execvp'。 – bombax

+0

我会建议加倍检查。我怀疑你在某个地方有单独的错误。也许重新发布有问题的所有代码,父母和孩子的问题。 – Duck