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