gpt4 book ai didi

C shell,父进程捕获的信号仍然转到子进程。

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:13:28 25 4
gpt4 key购买 nike

我正在用 C 编写一个基本的 unix shell,我想在 shell 中捕获 Cntrl-C 信号并将它们仅传递给前台进程,而不是后台进程。 shell 本身应该继续运行(确实如此),并且后台进程应该忽略 Cntrl-C 并且只被专门发送给它们的 kill 信号杀死,可能是通过命令行“kill pid”。但是,前台和后台进程都应使用 SIGCHLD 触发处理程序。然而,现在 shell 捕获了 Cntrl-C 信号,并且似乎正确地识别出没有前台进程可以将信号传递给,但后台进程仍然终止。

我尝试将后台进程的组 ID 设置为其他内容,这解决了问题,但它产生了一个新问题。当我这样做时,当后台进程完成时,我的信号处理程序不再捕获信号。

到目前为止,我已经查看了 SIGINT 的手册页,我已经阅读了大约 20 个 SO 答案,我已经尝试将子组的组 ID 设置为不同于父组的组 ID(解决了问题,但现在child 不能再将 SIGCHLD 发送给 parent),并且我在运行后台进程时检查了 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);
}
}
}

最佳答案

找到了我自己问题的答案。我已经尝试使用 setpid(0,0); 更改后台子进程的组 ID,这很有效,但产生了一个不同的问题。那个电话之后,我不再从 parent 那里的 child 那里捕捉到 SIGCHLD 信号。这是因为一旦更改了子进程组,它基本上不再连接到父进程以发出信号。这解决了后台进程从父进程捕获 Cntrl-C (SIGINT) 信号的问题(不良行为),但阻止了后台进程在完成时向父进程发送信号。解决了一个问题只会产生另一个问题。

相反,解决方案是检测子进程是否将被创建为前台进程或后台进程,如果是后台进程,则告诉它忽略 SIGINT 信号:signal(SIGINT, SIG_IGN);

关于C shell,父进程捕获的信号仍然转到子进程。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33808921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com