【问题标题】:errno set in child process after fork - OSX分叉后在子进程中设置 errno - OSX
【发布时间】:2013-12-16 04:42:44
【问题描述】:

这是我今天在 Mac OSX 上发现的一个奇怪的东西。

分叉成功后,errno 设置为 0 在父亲的进程中(如预期的那样),但在子进程中设置为 22。 这是源代码:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h>
#include <errno.h>

int main(int nbArgs, char** args){
   int pid;
   errno = 0;
   printf("Errno value before the call to fork : %d.\n", errno);
   if ((pid = fork()) == -1){
      perror("Fork failed.");
      exit(1);
   }
   if (pid == 0){
      printf("Child : errno value : %d.\n", errno);
   }else{
      printf("Father : pid value : %d ; errno value : %d.\n", pid, errno);
      wait(NULL);
   }
   exit(0);
}

还有执行轨迹:

Remis-Mac:TP3 venant$ ./errno_try
Errno value before the call to fork : 0.
Father : pid value : 9526 ; errno value : 0.
Child : errno value : 22.

据我所知,根据Opengroup specifications, “新进程(子进程)应是调用进程(父进程)的精确副本,除非下文详述 [...]”,包括全局变量 errno 的值 -_-

有没有人可以解释这种不受欢迎的行为?

【问题讨论】:

  • 这并不是特别不受欢迎的。大多数成功的系统调用都不需要设置 errno,并且 errno 可以是一个宏并且是特定于线程的。
  • 你是对的鸭子,这不是不可取的,但这种行为有时会误导......

标签: c macos unix fork errno


【解决方案1】:

很好奇...我可以使用 GCC 4.8.2 和 Clang 在 Mac OS X 10.9 Mavericks 上重现该问题。

POSIX 说某些失败的函数将设置errno(而fork() 是这些函数之一),但没有说成功的函数不会设置errno。例如,在 Solaris 上,如果输出流不是终端,许多标准 I/O 函数会设置 errno。但是,在 printf() 之后重置 errno = 0; 不会改变 Mac OS X 上的行为。

POSIX 2008(系统接口 - 一般信息:3.Error numbers):

某些函数在通过符号errno 访问的变量中提供错误号,该符号通过包含&lt;errno.h&gt; 标头来定义。 errno 的值只有在函数的返回值表明它是有效的时候才应该被检查。本卷 POSIX.1-2008 中的任何函数均不得将 errno 设置为零。对于进程的每个线程,errno 的值不应受到其他线程对errno 的函数调用或赋值的影响。

如果fork() 失败,则将设置errno 以指示失败。当它成功时,检查errno 在技术上是无效的。这就是为什么。

【讨论】:

    【解决方案2】:

    POSIX 说:

    成功完成后,fork() 将向子进程返回 0,并将子进程的进程 ID 返回给父进程。两个进程都应继续从 fork() 函数执行。否则返回-1给父进程,不创建子进程,设置errno表示错误。

    这意味着errno 被指定为仅在成功时设置。否则没有指定任何内容,因此您可以期待旧值 errno 或任何未指定的值。

    【讨论】:

    • 但是errno的旧值是0,而child中fork后的值是22,这很奇怪,因为errno在整个过程被复制时也会被复制。
    • @JonathanLeffler 正如您在回答中所说,没有什么可以阻止fork 在成功时将errno 设置为0,因为该值未指定。
    • 在 POSIX 中有一个命令,函数 nevererrno 设置为 0 - 请参阅我添加的引用。
    猜你喜欢
    • 2015-12-12
    • 1970-01-01
    • 2010-12-10
    • 2011-06-24
    • 1970-01-01
    • 2011-05-17
    • 1970-01-01
    • 2012-03-16
    • 2011-11-07
    相关资源
    最近更新 更多