【发布时间】:2019-01-14 21:07:42
【问题描述】:
我有一个程序需要一个最容易由脚本生成的文件列表(除了生成列表之外,它还做了一些可配置的事情)
本质上我是这样做的
fp = popen ("thescript", "r");
然后
while (fgets (buf, 1024, fp))
并处理这些行,最后:
rv = pclose (fp);
(bash) 脚本以 exit 0 结尾。但是当“正常”运行时,pclose 调用返回-1,ECHILD:没有子进程。
我喜欢 Linux 的地方在于,我通常可以通过运行 strace 来发现此类问题并查看实际发生的情况。这次不是:以普通用户身份运行 strace 时,脚本中的挂载失败,因此脚本执行 exit 1 和 rv 反映了这一点。当我将其更改为退出 0(当挂载失败时!)时,返回值 rv 反映了这一点(rv == 0,gui 不打印错误消息)。当我在跟踪时以 root 身份运行整个过程时,它可以工作(rv == 0,没有显示错误消息)。
我编写了简短的测试程序,一切都按预期工作。
起初我写的代码是专有的。决定发布它很简单......这是“故障”的实际代码。 “get_str_param”将返回要运行的脚本的名称。
files=popen(get_str_param("IMPORT_LIST"),"r");
//printf ("calling cmd for file list: %s\n", get_str_param("IMPORT_LIST"));
while(fgets(buf, 1024, files)) {
if((p=strstr(buf,".apl"))) {
*p=0;
if(strstr(buf," ")) continue; // ignore files with spaces
fl_add_browser_line(fd_import->applications,buf);
}
}
rv = pclose(files);
if (rv) {
printf ("Can't read file list! rv=%d\n", rv);
“fl_add_browser_line”来自“xforms”库。
那么...只有在不使用 strace 跟踪程序时,什么可能导致 ECHILD?
【问题讨论】:
-
如果您无法生成minimal reproducible example 来演示问题,并且无法提供实际存在问题的代码,您希望我们在这里做什么?对我们不允许看到的代码进行心理调试?
-
程序是否有自己的
SIGCHLD处理程序?pclose()必须使用waitpid()来获取子进程的退出状态。如果程序中的其他东西已经捕获了退出状态,或者将其声明为SIG_IGN,那么pclose()将没有任何东西可以检索。 -
strace也可能正在改变信号处理的时间,导致这个 heisenbug。 -
Barmar:你进入下一轮。 (荷兰语:“你继续洗洗衣机”)您回答了这个问题:“什么可能导致......”,可能正确的答案是:“一个 SIGCHLD 处理程序”。谢谢!我正在搜索暂时禁用 SIGCHLD 的解决方案。
-
@ShadowRanger 如果你想达到 400K 代表,你需要提高你的通灵能力。 :)