如何防止在 C++ 中使用 popen() 打开的进程接收 SIGINT 信号?

How to prevent a process opened with popen() in C++ from receiving SIGINT signal?

我使用 popen() 函数从 C++ 打开了一个进程 (GNUplot)。当我 Ctrl+C 终止进程时,GNUplot 也收到 SIGINT 信号。我想防止这种情况发生,因为它对我的工作有不利影响。 (我更喜欢用我自己的信号处理函数来处理信号)。我该怎么做?

我使用 plot '-' 命令绘图并遍历所有我想要绘制的值。如果 gnuplot 在中间接收到 SIGINT,它可能会在中间停止绘图而没有完成整个绘图。我想让它完成整个情节。这就是我的不利影响。

popen(3) 是 运行 命令字符串上的新 shell /bin/sh -c

shell的trap builtin正在处理信号;第一个参数是空的,它会忽略它。所以你可以做

 FILE* f = popen("trap '' TERM INT; gnuplot", "w");

顺便说一句,POSIX trap 要求信号命名时不带 SIG 前缀。

但这行不通,因为 gnuplot 本身是 明确 handling signals. There is no way to avoid that outside of gnuplot. But take advantage of the free software nature of gnuplot:下载它的源代码,研究它,并打补丁以适应你奇怪的需求。 FWIW,SIGINTsignal 出现在 gnuplot-5.0.5.

源代码的几个地方

但是,您应该考虑(而不是使用 popen)显式调用低级系统调用(forkexecvepipedup2waitpidsignal ...)。阅读 Advanced Linux Programming 了解详情。


我强烈怀疑你的问题是XY problem。您没有解释 "unfavorable effect" 您实际上想避免什么,我猜您可能会以其他方式避免它。

I plot using the plot '-' command and iterate through all the values I want to plot. If the gnuplot receives SIGINT in the middle, it might stop plotting in the middle without completing the entire plot. I want it to complete the entire plot.

实际上,您可以为 gnuplot 设置两个或三个管道(一个用于输入,一个用于输出,也许一个用于 stderr,如 gnuplot 侧所示)。您需要进行低级系统调用(显式调用 pipe(2), fork(2) etc etc...). Your program should then have some event loop (probably based upon poll(2)...). And you would send a print "DONE" command to gnuplot after every plot '-' (don't forget to initialize with the appropriate set print '-' or have another pipe for the stderr of gnuplot). Your event loop would then catch that DONE message to synchronize. Read also this.

我遇到了和你一样的问题。我正在使用带有 -batch 参数的 tc 命令,我需要让它保持活动状态,直到它在达到限制并关闭后退出。我的问题是我是 运行 两个异步 popen 进程,在抛出异常后,第二个进程被终止。大量内存转储等。在发现这个问题并修复它之后,我现在可以处理 SIGINT、SIGTERM、ctrl+c,而 tc 进程对此一无所知。不需要陷阱或类似的东西。