修改本机的系统时间对send_after的影响
前几天写了一个系统, 在本机(win7系统)自测时,为了测试方便,修改了本机的系统时间(将时间向未来调),但是随后,出现了诡异的bug,费了一段时间后,才发现原因:
修改系统时间之前,原本是每分钟触发一次的逻辑,在修改了系统时间后,每分钟可能会触发一次,但也可能会触发两次!
通过调试打印信息,发现当某分钟内触发两次时,是有规律的,一次是在该分钟的0秒,另一次是在该分钟的59秒。
程序的逻辑很简单,就是一个gen_server的模块,在init()时, 调用schedule_loop(),预定一个下一分钟的loop消息,在收到loop消息后,调用schedule_loop()以再次预定一个下一分钟的loop消息,并做相应处理,依此循环下去。
如下是schedule_loop()的实现:
schedule_loop() -> {_Hour, _Min, Sec} = erlang:time(), Intv = 60 - Sec, erlang:send_after(Intv*1000, self(), loop).
如下是收到loop消息对应的处理函数:
handle_info(loop, State) -> schedule_loop(), loop_handle(), {noreply, State};
修改系统时间为什么会产生这种影响? erlang:send_after()的实现原理是如何的? 目前还不清楚,以后有时间再研究下底层,这里先mark一下,以后得留心!
=========================
后记(2016.9.22):
看了LYSE的最后一章后,明白了原因:
将操作系统的时间向未来调之后, erlang内部的定时器相应地会有一点加速(time correction),R18之前可通过+c 参数设置,
"Time correction in versions prior to 18.0, if undesired, can be turned off by passing the +c
argument to the Erlang VM".
具体可以看: http://learnyousomeerlang.com/time