【问题标题】:Linux system() returns -1, ERRNO = 10 No child processes [closed]Linux system() 返回-1,ERRNO = 10 没有子进程[关闭]
【发布时间】:2019-03-13 19:52:20
【问题描述】:

当我在 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。

【问题讨论】:

  • 你为什么把extern int errno放在那里?您应该使用来自<errno.h> 的标准errno macro
  • 是的,我知道这是一个精简的摘要,但这里不足以回答这个问题。如果我根据我所看到的进行推测,我会猜测 /tmp/test.txt 已经存在并且不能被 OP 写入。但是谁知道可能省略了哪些实际相关的代码,这会导致我得出不同的猜测/结论?
  • 这真的是完整的程序吗?例如,如果您将 SA_NOCLDWAIT 添加到 SIGCHILD 处理程序的标志中,您当然可以触发此错误。
  • @sturcotte06:系统使用 shell 来执行参数。 Posix 标准引用:“system() 函数的行为就像使用 fork() 创建子进程一样,并且子进程使用 execl() 调用 sh 实用程序,如下所示:execl(<shell path>, "sh", "-c", command, (char *)0);
  • @JEtheDBA,我想要一个 善意 minimal reproducible example,正如 Barmar 已经要求的那样。如果到目前为止您所介绍的内容实际上是问题的特征,那么 MCVE 不必多于几行。我还想知道相对于运行程序的用户,您尝试将命令输出重定向到的文件的存在、所有权和权限。如果在强制模式下启用了 SELinux 属性(CentOS 7 的默认设置),则包括 SELinux 属性。

标签: c rhel7


【解决方案1】:

如果初始创建子进程(通过fork)或收集其退出状态(通过wait)失败,则值-1 只能由system 返回。由于传递给system 的命令有问题,这些事情都不会发生,因为该命令是在子进程中解释的。该命令的问题将显示为system 返回的值s 不等于0 或-1,并且WIFEXITED(s) && WEXITSTATUS(s) != 0WIFSIGNALED(s) 为真。 (sys/wait.h 中定义了宏 WIFEXITEDWIFSIGNALEDWEXITSTATUS。)(请参阅 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 处理程序,system 内部的 wait 故障可能会发生。例如,这个程序打印

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,这让我认为您的问题是由于waitSIGCHLD 处理程序之间的不良交互造成的。在errno 中获得“无子进程”(ECHILD) 与此假设一致,因为记录了wait 会产生该错误代码,而fork 不是。但这只是一个假设。为了更好地诊断您的问题,我们需要查看一个完整测试程序,我们可以自己编译和运行它,并观察与您完全相同的故障情况。请阅读并遵循https://stackoverflow.com/help/mcve 的说明。

【讨论】:

  • 感谢您的回答。实际程序根本不包含 errno。我添加了它以进行故障排除。主要问题是系统(cmd)成功运行“cmd”中的任何内容,但总是返回-1。甚至 system() 本身也会返回 -1。
  • @JEtheDBA 我能想到为什么会发生这种情况的原因,但我真的需要看到一个重现这种现象的完整测试程序system(cmd) 总是返回 - 1) 在我告诉你更多之前。
  • @JEtheDBA 实际上,还有一件事:在构建完整的测试程序时,请注意您的完整程序是否安装了任何信号处理程序,如果是,它是如何安装的。
猜你喜欢
  • 1970-01-01
  • 2019-08-13
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
相关资源
最近更新 更多