这是我今天在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上的行为。
某些函数在通过
errno
符号访问的变量中提供错误编号,通过包含<errno.h>
标头进行定义。errno
的值只能在被函数的返回值指示为有效时才被检查。 POSIX.1-2008的这个卷中没有函数将errno
为零。 对于进程的每个线程,errno
的值不应该被其他线程的函数调用或分配给errno
。
如果fork()
失败,那么将设置errno
来指示失败。 成功的时候,检查errno
技术上是errno
。 这是为什么。
POSIX说:
成功完成后,fork()将返回0给子进程,并将子进程的进程ID返回给父进程。 这两个过程将继续从fork()函数执行。 否则,-1将被返回到父进程,不会创建子进程,并且应设置错误号来指示错误。
这意味着errno
被指定为仅在成功时设置。 否则,没有指定,所以你可以期望一个旧的值errno
或任何未指定的值。