This change preents a race on the 'TZ' environ global variable in libc.
This should prevent a crash when base::Time::LocalMidnight calls out to
Time::FromExploded() which invokes mktime(), which relies on the timezone,
which is initialized when initializing libc (bionic on Android).
BUG=390567
Review URL: https://codereview.chromium.org/444473002
Cr-Commit-Position: refs/heads/master@{#288544}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288544 0039d316-1c4b-4281-b951-d872f2087c98
CrOS-Libchrome-Original-Commit: 5634ac560d1b61123d1b8dfb6660172d61187ffb
diff --git a/base/time/time_posix.cc b/base/time/time_posix.cc
index b5b8213..dcbd83c 100644
--- a/base/time/time_posix.cc
+++ b/base/time/time_posix.cc
@@ -26,9 +26,19 @@
#include "base/os_compat_nacl.h"
#endif
+#if !defined(OS_MACOSX)
+#include "base/lazy_instance.h"
+#include "base/synchronization/lock.h"
+#endif
+
namespace {
#if !defined(OS_MACOSX)
+// This prevents a crash on traversing the environment global and looking up
+// the 'TZ' variable in libc. See: crbug.com/390567.
+base::LazyInstance<base::Lock>::Leaky
+ g_sys_time_to_time_struct_lock = LAZY_INSTANCE_INITIALIZER;
+
// Define a system-specific SysTime that wraps either to a time_t or
// a time64_t depending on the host system, and associated convertion.
// See crbug.com/162007
@@ -36,6 +46,7 @@
typedef time64_t SysTime;
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
+ base::AutoLock locked(g_sys_time_to_time_struct_lock.Get());
if (is_local)
return mktime64(timestruct);
else
@@ -43,6 +54,7 @@
}
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
+ base::AutoLock locked(g_sys_time_to_time_struct_lock.Get());
if (is_local)
localtime64_r(&t, timestruct);
else
@@ -53,6 +65,7 @@
typedef time_t SysTime;
SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
+ base::AutoLock locked(g_sys_time_to_time_struct_lock.Get());
if (is_local)
return mktime(timestruct);
else
@@ -60,6 +73,7 @@
}
void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) {
+ base::AutoLock locked(g_sys_time_to_time_struct_lock.Get());
if (is_local)
localtime_r(&t, timestruct);
else