You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/03/22 08:31:21 UTC

[incubator-nuttx] branch master updated: libs/libc/time/localtime: fix race condition

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 6a6ad96  libs/libc/time/localtime: fix race condition
6a6ad96 is described below

commit 6a6ad96066fd1cad48af41316ea00de466060804
Author: chao.an <an...@xiaomi.com>
AuthorDate: Tue Feb 2 17:26:41 2021 +0800

    libs/libc/time/localtime: fix race condition
    
    fix race condition on create the instance of lcl/gmt
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 libs/libc/time/lib_localtime.c | 48 +++++++++++++++++++++++++++++++++---------
 1 file changed, 38 insertions(+), 10 deletions(-)

diff --git a/libs/libc/time/lib_localtime.c b/libs/libc/time/lib_localtime.c
index 4e48e44..c782321 100644
--- a/libs/libc/time/lib_localtime.c
+++ b/libs/libc/time/lib_localtime.c
@@ -321,6 +321,8 @@ static const char g_wildabbr[] = WILDABBR;
 static char g_lcl_tzname[MY_TZNAME_MAX + 1];
 static int g_lcl_isset;
 static int g_gmt_isset;
+static sem_t g_lcl_sem = SEM_INITIALIZER(1);
+static sem_t g_gmt_sem = SEM_INITIALIZER(1);
 
 /* Section 4.12.3 of X3.159-1989 requires that
  *    Except for the strftime function, these functions [asctime,
@@ -414,6 +416,28 @@ static FAR struct state_s *gmtptr;
  * Private Functions
  ****************************************************************************/
 
+static void tz_semtake(FAR sem_t *sem)
+{
+  int errcode = 0;
+  int ret;
+
+  do
+    {
+      ret = _SEM_WAIT(sem);
+      if (ret < 0)
+        {
+          errcode = _SEM_ERRNO(ret);
+          DEBUGASSERT(errcode == EINTR || errcode == ECANCELED);
+        }
+    }
+  while (ret < 0 && errcode == EINTR);
+}
+
+static void tz_semgive(FAR sem_t *sem)
+{
+  DEBUGVERIFY(_SEM_POST(sem));
+}
+
 static int_fast32_t detzcode(FAR const char *const codep)
 {
   int_fast32_t result;
@@ -1639,29 +1663,29 @@ static void gmtload(FAR struct state_s *const sp)
 
 static void tzsetwall(void)
 {
+  tz_semtake(&g_lcl_sem);
+
   if (g_lcl_isset < 0)
     {
+      tz_semgive(&g_lcl_sem);
       return;
     }
 
-  g_lcl_isset = -1;
-
   if (lclptr == NULL)
     {
       lclptr = lib_malloc(sizeof *lclptr);
-      if (lclptr == NULL)
-        {
-          settzname();          /* all we can do */
-          return;
-        }
     }
 
-  if (tzload(NULL, lclptr, TRUE) != 0)
+  if (lclptr != NULL && tzload(NULL, lclptr, TRUE) != 0)
     {
       gmtload(lclptr);
     }
 
   settzname();
+
+  g_lcl_isset = -1;
+
+  tz_semgive(&g_lcl_sem);
 }
 
 /* The easy way to behave "as if no library function calls" localtime
@@ -1791,16 +1815,20 @@ static struct tm *localsub(FAR const time_t * const timep,
 static struct tm *gmtsub(FAR const time_t * const timep,
                          const int_fast32_t offset, struct tm *const tmp)
 {
+  tz_semtake(&g_gmt_sem);
+
   if (!g_gmt_isset)
     {
       gmtptr = lib_malloc(sizeof *gmtptr);
-      g_gmt_isset = gmtptr != NULL;
-      if (g_gmt_isset)
+      if (gmtptr != NULL)
         {
           gmtload(gmtptr);
+          g_gmt_isset = 1;
         }
     }
 
+  tz_semgive(&g_gmt_sem);
+
   return timesub(timep, offset, gmtptr, tmp);
 }