From 5ee1d5909e9b0ce02dc5334f7f03f3ec3c7565f3 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 19 Apr 2022 10:20:57 +0200 Subject: erts: Fix localtime_r summer/winter-time change bug According to POSIX, localtime_r does not have to update the process internal tz data when called. So if time went from winter to summertime erts is running localtime_r may return an incorrect time. So we need to make sure to call tzset before each call to localtime_r. localtime is guaranteed to update the tz information, so no need to call it when using localtime. --- erts/emulator/sys/unix/erl_unix_sys.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'erts/emulator/sys/unix/erl_unix_sys.h') diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h index ae7a3ea23e..768f412c20 100644 --- a/erts/emulator/sys/unix/erl_unix_sys.h +++ b/erts/emulator/sys/unix/erl_unix_sys.h @@ -318,6 +318,27 @@ int sys_stop_hrvtime(void); /* No use in having other resolutions than 1 Ms. */ #define SYS_CLOCK_RESOLUTION 1 +ERTS_GLB_INLINE struct tm *sys_localtime_r(time_t *the_clock, struct tm *buff); + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE struct tm *sys_localtime_r(time_t *the_clock, struct tm *buff) { +#ifdef HAVE_LOCALTIME_R + tzset(); /* POSIX.1-2004 does not require tzset to be called within + localtime_r, so if summer/winter-time has passed localtime_r + will return the time when Erlang was started. So we need to + call tzset() before all localtime_r calls. + + localtime already calls tzset for each call, so the performance + penalty should be acceptable.... */ + return localtime_r(the_clock, buff); +#else + return localtime(the_clock); +#endif +} + +#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */ + /* These are defined in sys.c */ typedef void (*SIGFUNC)(int); extern SIGFUNC sys_signal(int, SIGFUNC); -- cgit v1.2.1