这是我今天在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 -_-
有没有人有解释这种不良行为的线索?
答案 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上的行为。
某些函数在通过包含
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
或任何未指定的值。