在fork – OSX之后,在subprocess中设置errno

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

在成功的分叉之后,父进程中的errno设置为0(如预期的那样),但是在subprocess中设置为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的规定 ,“新进程(subprocess)应该是调用进程(父进程)的精确副本,除了下面详细说明的”,包括全局variableserrno -_-

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

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

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

POSIX 2008(系统界面 – 一般信息:3. 错误号码 ):

某些函数在通过errno符号访问的变量中提供错误编号,通过包含<errno.h>标头进行定义。 errno的值只能在被函数的返回值指示为有效时才被检查。 POSIX.1-2008的这个卷中没有函数将errno为零。 对于进程的每个线程, errno的值不应该被其他线程的函数调用或分配给errno

如果fork()失败,那么将设​​置errno来指示失败。 成功的时候,检查errno技术上是errno 。 这是为什么。

POSIX说:

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

这意味着errno被指定为仅在成功时设置。 否则,没有指定,所以你可以期望一个旧的值errno或任何未指定的值。