肯·托马斯的回答可能是正确的,但我很好奇更具体的答案,因为我仍然发现单线程程序执行如此简单/常见操作后的缓慢意外行为fork
ing。检查后http://opensource.apple.com/source/Libc/Libc-997.1.1/stdtime/FreeBSD/localtime.c http://opensource.apple.com/source/Libc/Libc-997.1.1/stdtime/FreeBSD/localtime.c(不能100%确定这是正确的来源),我想我有一个答案。
该代码使用被动通知来确定时区是否已更改(与stat
ing /etc/localtime
每次)。看起来注册的通知令牌在子进程中变得无效fork
ing。此外,代码将使用无效令牌产生的错误视为时区已更改的积极通知,并继续读取/etc/localtime
每次。我想这是你可以得到的那种未定义的行为fork
英?不过,如果图书馆注意到该错误并重新注册通知,那就太好了。
以下是 localtime.c 中的代码片段,它将错误值与状态值混合在一起:
nstat = notify_check(p->token, &ncheck);
if (nstat || ncheck) {
我演示了使用此程序分叉后注册令牌变得无效:
#include <notify.h>
#include <stdio.h>
#include <stdlib.h>
void bail(char *msg) {
printf("Error: %s\n", msg);
exit(1);
}
int main(int argc, char **argv) {
int token, something_changed, ret;
notify_register_check("com.apple.system.timezone", &token);
ret = notify_check(token, &something_changed);
if (ret)
bail("notify_check #1 failed");
if (!something_changed)
bail("expected change on first call");
ret = notify_check(token, &something_changed);
if (ret)
bail("notify_check #2 failed");
if (something_changed)
bail("expected no change");
pid_t c = fork();
if (c == 0) {
ret = notify_check(token, &something_changed);
if (ret) {
if (ret == NOTIFY_STATUS_INVALID_TOKEN)
printf("ret is invalid token\n");
if (!notify_is_valid_token(token))
printf("token is not valid\n");
bail("notify_check in fork failed");
}
if (something_changed)
bail("expected not changed");
exit(0);
}
wait(NULL);
}
并像这样运行:
muir-mb:projects muir$ clang -o notify_test notify_test.c
muir-mb:projects muir$ ./notify_test
ret is invalid token
token is not valid
Error: notify_check in fork failed