From de9cdcb2d9e64e5b12dcc6de37a6d910b196ad43 Mon Sep 17 00:00:00 2001 From: Jesse Riemens Date: Wed, 13 Aug 2025 05:49:05 -0400 Subject: [PATCH] [vm/runtime] Call `tzset()` before `localtime_r()`. POSIX doesn't guarantee that the timezone is set correctly before calling `localtime_r()`, so we need to call `tzset()` first to ensure that the timezone information is up-to-date. As the glibc manual states: > According to POSIX.1-2001, `localtime()` is required to behave as though `tzset(3)` was called, while `localtime_r()` does not > have this requirement. For portable code, `tzset(3)` should be called before `localtime_r()`. This change doesn't apply to Android, as from Android O and later Bionic libc handles timezone changes automatically. --- runtime/vm/os_android.cc | 3 +++ runtime/vm/os_linux.cc | 1 + 2 files changed, 4 insertions(+) diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc index 5547201ae105..e9fc73ced95b 100644 --- a/runtime/vm/os_android.cc +++ b/runtime/vm/os_android.cc @@ -102,6 +102,9 @@ intptr_t OS::ProcessId() { static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { time_t seconds = static_cast(seconds_since_epoch); if (seconds != seconds_since_epoch) return false; + // No need to call tzset() before localtime_r() because bionic + // will handle timezone changes for us (starting from Android O). + // See https://android.googlesource.com/platform/bionic/+/ea87716696bf635706b6f3fa56b8a145add83aff struct tm* error_code = localtime_r(&seconds, tm_result); return error_code != nullptr; } diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc index a09fbfddc448..8bdfda024d31 100644 --- a/runtime/vm/os_linux.cc +++ b/runtime/vm/os_linux.cc @@ -418,6 +418,7 @@ intptr_t OS::ProcessId() { static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { time_t seconds = static_cast(seconds_since_epoch); if (seconds != seconds_since_epoch) return false; + tzset(); // Not guaranteed by POSIX to be called by `localtime_r`. struct tm* error_code = localtime_r(&seconds, tm_result); return error_code != nullptr; }