errno在fork之后设置在子进程中 - OSX

时间:2013-11-30 00:11:08

标签: c macos unix fork errno

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

在成功的fork之后,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 -_-

有没有人有解释这种不良行为的线索?

2 个答案:

答案 0 :(得分:5)

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

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

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

  

某些函数在通过包含errno标头定义的符号<errno.h>访问的变量中提供错误编号。仅当errno被函数的返回值指示为有效时,才应检查errno的值。本卷POSIX.1-2008中的任何功能都不应将errno设置为零。对于进程的每个线程,errno的值不受其他线程的函数调用或fork()赋值的影响。

如果errno失败,则会设置errno以指示失败。如果成功,则检查{{1}}在技术上无效。这就是原因的证明。

答案 1 :(得分:1)

POSIX说:

  

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

表示errno指定仅在成功时设置。否则,不会指定任何内容,因此您可以期望旧值errno或任何未指定的值。