使用 libfaketime 时,setTimeout 在 Mac OS 和 Linux 上的行为不同

setTimeout behaves differently on Mac OS and Linux when using libfaketime

当使用libfaketime改变进程的时间速度时,setTimout设置的超时根据运行ning在Linux下改变的时间到期但是根据MacOS.

下运行ning时的原系统时间

在Mac OS:

DYLD_INSERT_LIBRARIES=src/libfaketime.1.dylib DYLD_FORCE_FLAT_NAMESPACE=y FAKETIME="@2020-12-24 00:00:00 x3600" node

> setTimeout(() => {console.log('hello');}, 3600 * 1000); // Takes an hour

在Linux中:

LD_PRELOAD=src/libfaketime.1.so FAKETIME="@2020-12-24 00:00:00 x3600" node

> setTimeout(() => {console.log('hello');}, 3600 * 1000); // Takes a second

在调查这个问题时,我注意到 libcclock_gettime 函数由 Linux 下的 node.js (libuv?) 轮询,但是当运行宁下 Mac OS。 (我在 libfaketime 函数中添加了一些 printfs)

导致 Mac OS 和 Linux 之间行为差异的 node.js(libuv?)的实施有何不同?为什么会存在这种实施差异?

我的另一个观察是,当使用 libfaketime 冻结时间时,setImmediatesetTimeout(cb, 0) 的行为在 Linux 下有所不同,因为回调是 运行 在使用 setImmediate 时使用 setTimeout(cb, 0).

绝对是libuv的区别。达尔文不会support CLOCK_MONOTONIC*, therefore mach_absolute_time() must be called为了得到当前时间。这最终会绕过 libfaketime,导致客户端代码在 OS X 上实时 运行。