当我在RHEL 7.4中运行以下C代码时:
errno = 0;
status = system("ls >> /tmp/test.txt");
sprintf(msg, "Value of errno: %d\n", errno);
sprintf(msg, "Status: %d ", status);
os_log_msg(msg);
我得到-1的返回码和errno = 10(没有子进程)。 /tmp/test.txt文件实际上已创建,因此它可以正常工作,但程序会看到非零返回码并退出。
问题是该命令在HP-UX 11.11中返回0,但我们迁移到RHEL 7.4,现在我们得到-1。
如果初始创建子进程(通过system
)或其退出状态集合(通过fork
)失败,则值-1只能由wait
返回。由于传递给system
的命令存在问题,因此这两件事都不会发生,因为该命令在子进程中被解释。该命令的问题将显示为system
返回的值s
不等于0或-1,并且WIFEXITED(s) && WEXITSTATUS(s) != 0
或WIFSIGNALED(s)
为真。 (宏WIFEXITED
,WIFSIGNALED
和WEXITSTATUS
在sys/wait.h
中定义。)(参见the POSIX specification for system
以了解为什么会发生这种情况。)
fork
故障通常仅发生在系统范围的资源耗尽和/或严重强加的资源配额中。例如,该程序打印
true: status=-1 errno=11 (Resource temporarily unavailable)
当我运行它。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
int main(void)
{
struct rlimit rl;
rl.rlim_cur = 1;
rl.rlim_max = 1;
setrlimit(RLIMIT_NPROC, &rl);
int status = system("true");
printf("true: status=%d errno=%d (%s)\n", status, errno, strerror(errno));
return 0;
}
如果你有一个窃取等待状态的SIGCHLD处理程序,可能会发生wait
内部的system
故障。例如,该程序打印
true: status=-1 errno=10 (No child processes)
当我运行它。 (SIGCHLD处理程序可以通过其他几种方式干扰system
;这只是我能想到的最短的演示程序。)
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
int main(void)
{
signal(SIGCHLD, SIG_IGN);
int status = system("true");
printf("true: status=%d errno=%d (%s)\n", status, errno, strerror(errno));
return 0;
}
你说无论你传递给system
的命令都能正确执行,但system
仍然返回-1,这让我觉得你的问题是由于wait
和SIGCHLD
处理程序之间的不良交互。在ECHILD
中获得“无子过程”(errno
)与此假设一致,因为wait
被记录为产生该错误代码,而fork
则不然。但这只是一个假设。为了更好地诊断你的问题,我们需要看到一个完整的测试程序,我们可以为自己编译和运行,并观察完全相同的故障情况。请阅读并按照https://stackoverflow.com/help/mcve上的说明进行操作。