如何防止子进程中的SIGINT传播并杀死父进程? [英] How to prevent SIGINT in child process from propagating to and killing parent process?

查看:83
本文介绍了如何防止子进程中的SIGINT传播并杀死父进程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近学习了如何完成整个fork/exec/wait事情,并最终编写了一些看起来像这样的代码:

I've recently learned how to do the whole fork/exec/wait thing and ended up writing some code that looked like this stripped down:

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

int main() {
  pid_t x = fork();
  if (x == 0) {
    execlp("sqlite3", "sqlite3");
    printf("exec failed\n");
  } else {
    wait(NULL);
    printf("Hi\n");
  }
}

这很好,实际上最终打开了sqlite3 shell,但是有一个问题.如果您Ctrl + Csqlite3外壳程序中退出,那么它也会终止父进程,并且行printf("Hi\n")永远不会运行.

This works out pretty well, and actually ends up opening the sqlite3 shell, but there's one problem. If you Ctrl + C out of the sqlite3 shell, then it also terminates the parent process and the line printf("Hi\n") never runs.

我认为这是因为SIGINT正在传播到父进程,并且在进一步研究之后,我读到SIGINT将终止同一组中的所有进程,这意味着由于父级和子级共享它们所在的同一组都被终止了.

I assumed this was because the SIGINT was being propagating to the parent process, and after looking into it further, I read that a SIGINT will terminate all processes in the same group, meaning since the parent and child share the same group they're both terminated.

我试图通过尝试这样调用setpgid来解决此问题:

I tried to fix this by doing trying to call setpgid like so:

int main() {
  pid_t x = fork();
  if (x == 0) {
    setpgid(getpid(), getpid()); // <-- Added in this line
    execlp("sqlite3", "sqlite3");
    printf("exec failed\n");
  } else {
    wait(NULL);
    printf("Hi\n");
  }
}

可以运行,但是破坏了sqlite3提示.此外,在这种情况下,Ctrl + C仍然杀死了父级.我决定尝试进一步缩小范围,然后发现一些奇怪的东西并陷入困境.只是将getpid()调用置于派生位置,将使execlp()失败.

which ran fine, but that broke the sqlite3 prompt. Moreover Ctrl + C still killed the parent in this case. I decided to try to narrow it down even more, and then found something weird, and got stumped. Just putting a getpid() call into the fork will make execlp() fail.

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

int main() {
  pid_t x = fork();
  if (x == 0) {
    getpid(); // <--- just adding this in makes it fail
    execlp("sqlite3", "sqlite3");
    printf("exec failed\n");
  } else {
    wait(NULL);
    printf("Hi\n");
  }
}

,甚至不仅用于sqlite3,而且还用于诸如execlp("ls", "ls")的简单内容(尽管这可能与原始问题无关).

and not even just for sqlite3, but for simple stuff like execlp("ls", "ls") as well (this might be unrelated to the original question though).

我有点不知所措,我想知道是否有人可以指出我正确的方向.我不太确定该怎么办.

I'm in a bit over my head and I was wondering if anyone could point me in the right direction. I'm not quite sure what to do from here.

  • 我正在使用OSX 10.11,并且正在使用clang进行编译.
  • clang --version:Apple LLVM版本8.0.0(clang-800.0.42.1)
  • I'm on OSX 10.11, and am compiling with clang.
  • clang --version: Apple LLVM version 8.0.0 (clang-800.0.42.1)

推荐答案

您可以捕获SIGINT或编写信号处理程序. 使用以下代码:

you can either catch the SIGINT or write a signal handler. use the code below:

signal(SIGINT, sig_handler);
void sig_handler(int signo)
{
  if (signo == SIGINT)
    printf("received SIGINT\n");
}

这篇关于如何防止子进程中的SIGINT传播并杀死父进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆