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 2022/11/28 10:04:46 UTC

[nuttx] 02/02: localtime: fix deadlock when print syslog in romfs

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/nuttx.git

commit f243e4f268d6370b4d4aad5415310c1b0399b9a5
Author: ligd <li...@xiaomi.com>
AuthorDate: Tue Nov 15 18:35:32 2022 +0800

    localtime: fix deadlock when print syslog in romfs
    
    thread1:
    romfs_seek -> take romfslock -> syslog -> tzset
    thread2:
    sylsog -> tzset -> tz_load -> romfs_open -> deadlock
    
    Signed-off-by: ligd <li...@xiaomi.com>
---
 libs/libc/time/lib_localtime.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/libs/libc/time/lib_localtime.c b/libs/libc/time/lib_localtime.c
index 528dc86688..93985a4002 100644
--- a/libs/libc/time/lib_localtime.c
+++ b/libs/libc/time/lib_localtime.c
@@ -1901,6 +1901,11 @@ static FAR struct tm *localsub(FAR const time_t *timep,
       return gmtsub(timep, offset, tmp);
     }
 
+  if (nxrmutex_is_hold(&g_lcl_lock))
+    {
+      return NULL;
+    }
+
   if ((sp->goback && t < sp->ats[0]) ||
       (sp->goahead && t > sp->ats[sp->timecnt - 1]))
     {
@@ -2746,7 +2751,6 @@ static int zoneinit(FAR const char *name)
 void tzset(void)
 {
   FAR const char *name;
-  int lcl = -1;
 
 #ifndef __KERNEL__
   if (up_interrupt_context() || (sched_idletask() && OSINIT_IDLELOOP()))
@@ -2755,23 +2759,24 @@ void tzset(void)
     }
 #endif
 
-  nxrmutex_lock(&g_lcl_lock);
-
   name = getenv("TZ");
-  if (name != NULL)
+  if (name == NULL)
     {
-      lcl = 1;
+      return;
     }
 
-  if (lcl < 0 && g_lcl_isset < 0)
+  if (g_lcl_isset > 0 && strcmp(g_lcl_tzname, name) == 0)
     {
-      goto out;
+      return;
     }
-  else if (lcl > 0 && g_lcl_isset > 0 && strcmp(g_lcl_tzname, name) == 0)
+
+  if (nxrmutex_is_hold(&g_lcl_lock))
     {
-      goto out;
+      return;
     }
 
+  nxrmutex_lock(&g_lcl_lock);
+
   if (g_lcl_ptr == NULL)
     {
       g_lcl_ptr = lib_malloc(sizeof(*g_lcl_ptr));
@@ -2786,15 +2791,11 @@ void tzset(void)
       zoneinit("");
     }
 
-  if (lcl > 0)
-    {
-      strcpy(g_lcl_tzname, name);
-    }
+  strcpy(g_lcl_tzname, name);
 
 tzname:
   settzname();
-  g_lcl_isset = lcl;
-out:
+  g_lcl_isset = 1;
   nxrmutex_unlock(&g_lcl_lock);
 }