[erlang-questions] Changing time

Per Hedeland <>
Sun May 11 22:08:43 CEST 2008


Hi,

The Erlang emulator includes some sophisticated code to deal with sudden
changes to the system time, which tries to maintain "delta" timers such
as 'receive ... after' while gradually adapting time-of-day as seen by
the emulator to agree with with the new system time.

Unfortunately this code works only on Linux and Solaris (maybe on
Windows too, I wouldn't know) - on other systems, e.g. *BSD, you can
play this game:

1. Start erlang.
2. Set the system time back by, say, 5 minutes.
3. Invoke timer:sleep(1).
4. Watch the call take 5 minutes to complete.

Now, system time "shouldn't" move backwards, but in real life it
sometimes does, and "don't do that" isn't always a viable response. And
while "weird" things may happen to timers that are running across the
time change, I think it definitely violates the POLA that timers started
*after* the time change are completely broken.

A suggested fix is below (diff against R12B-2) - as far as I can see, it
will work pretty well both for timers running across the time change and
for timers started after it - worst case it will cause one timer to have
double the requested timeout, but once the new system time has been
discovered, it should Do the Right Thing, and it's independent of the
magnitude of the time change.

By the way, the discussion about the +c option in the erl(1) man page is
wrong - Erlang timers are not based on erlang:now/0. Timers and
erlang:now/0 use the same underlying timing mechanism, which may or may
not have compensation for "sudden changes of system time" depending on
the OS and the usage of +c, but erlang:now/0 fulfills its promise of
delivering monotonously increasing numbers regardless - also with the
patch below.

--Per Hedeland

--- erts/emulator/beam/erl_time_sup.c.orig	2008-04-07 15:58:13.000000000 +0200
+++ erts/emulator/beam/erl_time_sup.c	2008-05-09 23:15:39.000000000 +0200
@@ -383,13 +383,12 @@
 	CLOCK_RESOLUTION;
 
     /* Sometimes the time jump backwards,
-       resulting in a negative elapsed time. We compensate for
-       this by simply pretend as if the time stood still. :) */
+       resulting in a negative elapsed time. */
 
     if (elapsed > 0) {
 	do_time_add(elapsed);
-	last_delivered = cur_time;
     }
+    last_delivered = cur_time;
 }
 #endif
 






More information about the erlang-questions mailing list