我在C编写一个基本的unix shell,我想在shell中捕获Cntrl-C信号,并将它们仅传递给前台进程,但不传递给后台进程。 shell本身应该继续运行(而且它会),后台进程应该忽略一个Cntrl-C并且只能通过专门发送给它们的kill信号来杀死,可能通过命令行“kill pid”。但是,前台和后台进程都应该使用SIGCHLD触发处理程序。然而,现在,外壳捕捉到Cntrl-C信号,并且似乎正确地识别出没有前台进程传递信号,但后台进程仍然死亡。C shell,父类捕获的信号仍然进入子进程。
我试着将后台进程的组ID设置为别的,并且解决了这个问题,但是它创建了一个新问题。当我这样做时,当后台进程完成时,我的信号处理程序不再捕获信号。
到目前为止,我已经看过SIGINT的手册页,我已经阅读了20个左右的答案,我试着将孩子的组ID设置为与父组不同的东西(解决问题,但现在孩子不能再发送SIGCHLD给父母了),并且我在运行后台进程时检查了childid!= foreground process和foregroundProcess == 0。但是后台进程仍然被杀死。有任何想法吗?
我想我的问题是在我的信号处理程序的地方,但不是很确定:
主:
struct sigaction sa;
sa.sa_handler = &handleSignal; /*passing function ref. to handler */
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask); /*block all other signals while handling sigs */
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
handleSignal看起来是这样的:
void handleSignal(int signal){
int childid;
switch (signal) {
/*if the signal came from a child*/
case SIGCHLD:
/*get the child's id and status*/
childid = waitpid(-1,&childStatus,0);
/*No action for foreground processes that exit w/status 0 */
/*otherwise show pid & showStatus */
if ((childid != foregroundProcess)){
printf("pid %i:",childid);
showStatus(childStatus);
fflush(stdout);
}
break;
/* if signal came from somewhere else, pass it to foreground child */
/* if one exists. */
default:
printf("Caught signal: %i and passing it", signal);
printf(" to child w/pid: %i\n\n:", foregroundProcess);
fflush(stdout);
/*If there is a child, send signal to it. */
if (foregroundProcess){
printf("trying to kill foreground.\n");
fflush(stdout);
kill(foregroundProcess, signal);
}
}
}
在一个不相关的音符,如果你还没有改变的'stdout'你不需要,只要你最终所有的输出与换行符明确地刷新它的缓冲模式。 'stdout'默认是行缓冲的。 –
感谢Joachim。由于printf的存在是为了调试目的,所以我对缓冲区进行了额外的细心处理。我不希望某些打印线实际上被打印到不打印,因为另一个打印线在此期间做了一些奇怪的事情。无论如何,所有这些printf可能都会在最终产品中消失。 – Fish314