C 在带busybox的嵌入式linux上使用system()时,SIGHUP信号处理程序重置为默认值

C 在带busybox的嵌入式linux上使用system()时,SIGHUP信号处理程序重置为默认值,c,linux,sh,busybox,C,Linux,Sh,Busybox,我正在使用busybox开发嵌入式linux。作为应用程序的一部分,我有一个rc.init脚本E80 startmyprog。该脚本正在调用我的程序prog trap“HUP startmyprog>${LOGFILE}2>&1信号 现在,在我的程序中的某个时候,我需要启动另一个进程,给它一些输入,并检查它是否在标准输出上打印“是”。我正在使用这个系统来做这件事 const int ret=system(“[`echo input | second_process`==yes]”); 正常行

我正在使用busybox开发嵌入式linux。作为应用程序的一部分,我有一个rc.init脚本E80 startmyprog。该脚本正在调用我的程序prog

trap“HUP
startmyprog>${LOGFILE}2>&1信号
现在,在我的程序中的某个时候,我需要启动另一个进程,给它一些输入,并检查它是否在标准输出上打印“是”。我正在使用这个系统来做这件事

const int ret=system(“[`echo input | second_process`==yes]”);
正常行为是
WIFEXITED(ret)
为真,而
WEXITSTATUS(ret)
为0或1

但在某些情况下,如果时间不正确,
WIFSIGNALED(ret)
为真,
WTERMSIG(ret)
为1(SIGHUP)

调试表明,如果I
execl(“第二个\u进程”、“第二个\u进程”、(char*)NULL)
第二个\u进程中的信号处理程序状态正确设置为SIGHUP=ignore。但如果我使用
系统
,则第二个\u进程具有SIGHUP=default

我的问题是:

那里发生了什么事?谁在启动时重置SIGHUP信号处理程序?是贝壳吗?有没有办法防止这种情况发生?(在sh手册页中,我没有看到命令行选项看起来如此。)


我知道我可以做一个变通方法,设置管道、fork、exec second_进程、将输入写入管道、从管道读取输出和解析输出,但与system one liner相比,这是很多东西,我很有可能会错过一些东西并出错。

我不认为这正是发生的事情。当您在shell中键入“trap”时,您要求它列出为该信号建立的操作。当您调用子shell时,您没有给它任何操作,因此它不会显示任何操作(它不知道您给它的父级提供了什么),但这并不意味着它已经重置了SIGHUP状态

试试这个小脚本,它可以证明SIGHUP仍然被忽略,即使“trap”没有显示任何内容:

trap "" HUP
echo "TRAPs in parent"
trap
sh -c 'echo "TRAPs in child"; trap; sleep 5; echo "Still here. Traps: "; trap' &
child=$!
sleep 1
kill -HUP $child
echo 'Killed child'

深入研究Linux上运行的busybox的源代码,我发现busybox中的shell正在调用
信号(SIGHUP,SIG_DFL)在初始化期间。这将sighup处理程序重置为默认值。因此,shell本身及其运行的程序(随
-c…
提供)使用默认的SIGHUP处理程序运行


我看不到绕过重置SIGHUP信号处理程序的代码路径,因此我似乎无法通过
system()

实现我想要的功能,因此我与bash的比较与我在c程序和
system
中观察到的不一样。很抱歉出现这种混乱,我将删除bash比较部分。请尝试
strace-ff-o/tmp/foo程序
——这将在您的程序上运行strace,跟踪fork,并将每个进程的跟踪结果存储在/tmp/foo.nnn中。我想您会发现系统(3)没有重置SIGHUP处理程序,尽管可能还有其他的事情值得一提。之前,我确实运行了strace,但仅用于其他一些测试。我重播了你的建议。日志显示生成的sh调用rt_sigaction:
rt_sigaction(SIGHUP,{0x10000000,[],0},{SIG_DFL,[],sau NOCLDSTOP},16)=0