【问题标题】:How to prevent a process opened with popen() in C++ from receiving SIGINT signal?如何防止在 C++ 中使用 popen() 打开的进程接收 SIGINT 信号?
【发布时间】:2017-05-07 18:14:16
【问题描述】:

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

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

【问题讨论】:

  • 请说明您希望避免的不利影响。
  • 我终于对你的问题投了反对票,因为你没有编辑它来解释你想避免什么“不利影响”。
  • @BasileStarynkevitch 我编辑了问题

标签: c++ signals popen sigterm


【解决方案1】:

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

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

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

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

但这行不通,因为gnuplot 本身是明确 handling signals。在gnuplot 之外没有办法避免这种情况。但是利用gnuplotfree software 特性:下载它的源代码,研究它,然后修补它以满足您的奇怪需求。 FWIW、SIGINTsignal出现在gnuplot-5.0.5源代码的几个地方。

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


我强烈怀疑您的问题是XY problem。你没有解释你真正想要避免的“不利影响”,我猜你可能会避免它。

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

实际上,您可以为gnuplot 设置两个或三个管道(一个用于输入,一个用于输出,也许一个用于stderr,如gnuplot 侧所示)。您需要进行低级系统调用(显式调用pipe(2)fork(2) 等...)。然后你的程序应该有一些event loop(可能基于poll(2)...)。你会在每个plot '-' 之后发送一个print "DONE" command 到gnuplot(不要忘记使用适当的set print '-' 进行初始化,或者为gnuplotstderr 设置另一个管道) .然后,您的事件循环将捕获该 DONE 消息以进行同步。另请阅读this

【讨论】:

  • 我的建议是避免使用popen 并使用较低级别的系统调用。
  • 我打错了,是trap '' TERM 不是SIGTERM;但我建议您避免使用popen
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2011-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-27
    • 2021-05-24
    • 1970-01-01
    • 2016-03-22
    相关资源
    最近更新 更多