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

时间:2015-05-20 13:51:47

标签: c linux sh busybox

我正在使用busybox的嵌入式Linux。作为我的应用程序的一部分,我有一个rc.init脚本E80-startmyprog。那个脚本正在调用我的程序编程。

trap "" HUP
startmyprog >${LOGFILE} 2>&1 </dev/null &

startmyprog() {
  prog
}

在我的程序中,我可以看到信号处理程序设置为忽略SIGHUP。我正在检查

struct sigaction act;
sigaction(1, NULL, &act);
printf("action %p\n", act.sa_sigaction);  // prints out 1 -> SIG_IGN

现在在我的程序中的一段时间我需要启动另一个进程,给它一些输入并检查它是否在stdout上打印“是”。我正在使用系统来做到这一点。

const int ret = system("[ `echo input | second_process` == yes ]");

正常行为是WIFEXITED(ret)为真且WEXITSTATUS(ret)为0或1。

但在某些情况下,不幸的时间WIFSIGNALED(ret)为真,WTERMSIG(ret)为1(SIGHUP)。

调试显示,如果我execl("second_process", "second_process", (char*)NULL),则second_process中的信号处理程序状态被正确设置为SIGHUP = ignore。但是如果我使用system,则second_process具有SIGHUP = default。

我的问题是:

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

我知道我可以做一个解决方法并设置一个管道,fork,exec second_process,将输入写入管道,读取管道输出和解析输出,但与系统一个内衬相比,这是很多东西我会错过一些错误的机会。

2 个答案:

答案 0 :(得分:1)

我不认为这正是发生的事情。当你在shell中输入'trap'时,你要求它列出它为该信号建立的动作。当你调用子shell时,你没有给它任何动作,因此它不会显示任何动作(它不知道你给它的父级的内容),但这并不意味着它已经重置了SIGHUP状态。 / p>

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

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'

答案 1 :(得分:0)

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

我看不到绕过重置SIGHUP信号处理程序的代码路径,所以我似乎无法用system()实现我想要的。