Fix: Setting env YAZ_LOG makes YAZ hang YAZ-745
[yaz-moved-to-github.git] / src / log.c
index 97bc43b..265dd77 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2013 Index Data
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
  */
 
 #include <yaz/errno.h>
 #include <yaz/thread_id.h>
 #include <yaz/log.h>
+#include <yaz/mutex.h>
 #include <yaz/snprintf.h>
 #include <yaz/xmalloc.h>
+#if YAZ_POSIX_THREADS
+#include <pthread.h>
+#endif
 
 static int l_level = YLOG_DEFAULT_LEVEL;
 
@@ -99,21 +103,32 @@ static struct {
 
 static unsigned int next_log_bit = YLOG_LAST_BIT<<1; /* first dynamic bit */
 
-static void internal_log_init(void)
+static YAZ_MUTEX log_mutex = 0;
+
+static void yaz_log_lock(void)
 {
-    static int mutex_init_flag = 0; /* not yet initialized */
-    char *env;
+    yaz_mutex_enter(log_mutex);
+}
 
-    if (mutex_init_flag)
-        return;
-    mutex_init_flag = 1; /* here, 'cause nmem_mutex_create may call yaz_log */
+static void yaz_log_unlock(void)
+{
+    yaz_mutex_leave(log_mutex);
+}
 
+void yaz_log_init_globals(void)
+{
+    char *env;
+
+    if (log_mutex == 0)
+        yaz_mutex_create(&log_mutex);
+#if YAZ_POSIX_THREADS
+    pthread_atfork(yaz_log_lock, yaz_log_unlock, yaz_log_unlock);
+#endif
     env = getenv("YAZ_LOG");
     if (env)
         l_level = yaz_log_mask_str_x(env, l_level);
 }
 
-
 FILE *yaz_log_file(void)
 {
     FILE *f = 0;
@@ -137,7 +152,7 @@ void yaz_log_close(void)
 
 void yaz_log_init_file(const char *fname)
 {
-    internal_log_init();
+    yaz_init_globals();
 
     yaz_log_close();
     if (fname)
@@ -197,7 +212,7 @@ static void rotate_log(const char *cur_fname)
 
 void yaz_log_init_level(int level)
 {
-    internal_log_init();
+    yaz_init_globals();
     if ( (l_level & YLOG_FLUSH) != (level & YLOG_FLUSH) )
     {
         l_level = level;
@@ -250,7 +265,7 @@ void yaz_log_init_prefix2(const char *prefix)
 
 void yaz_log_init(int level, const char *prefix, const char *fname)
 {
-    internal_log_init();
+    yaz_init_globals();
     yaz_log_init_level(level);
     yaz_log_init_prefix(prefix);
     if (fname && *fname)
@@ -342,12 +357,14 @@ static void yaz_log_do_reopen(const char *filemode)
     struct tm *tm;
 #endif
 
+    yaz_log_lock();
 #if HAVE_LOCALTIME_R
     localtime_r(&cur_time, tm);
 #else
     tm = localtime(&cur_time);
 #endif
     yaz_log_open_check(tm, 1, filemode);
+    yaz_log_unlock();
 }
 
 
@@ -377,8 +394,7 @@ static void yaz_log_to_file(int level, const char *log_message)
     struct tm *tm;
 #endif
 
-    internal_log_init();
-
+    yaz_log_lock();
 #if HAVE_LOCALTIME_R
     localtime_r(&ti, tm);
 #else
@@ -436,6 +452,7 @@ static void yaz_log_to_file(int level, const char *log_message)
         if (l_level & YLOG_FLUSH)
             fflush(file);
     }
+    yaz_log_unlock();
 }
 
 void yaz_log(int level, const char *fmt, ...)
@@ -445,7 +462,7 @@ void yaz_log(int level, const char *fmt, ...)
     FILE *file;
     int o_level = level;
 
-    internal_log_init();
+    yaz_init_globals();
     if (!(level & l_level))
         return;
     va_start(ap, fmt);
@@ -539,7 +556,7 @@ int yaz_log_module_level(const char *name)
     int i;
     char clean[255];
     char *n = clean_name(name, strlen(name), clean, sizeof(clean));
-    internal_log_init();
+    yaz_init_globals();
 
     for (i = 0; mask_names[i].name; i++)
         if (0==strcmp(n, mask_names[i].name))
@@ -556,7 +573,7 @@ int yaz_log_module_level(const char *name)
 
 int yaz_log_mask_str(const char *str)
 {
-    internal_log_init(); /* since l_level may be affected */
+    yaz_init_globals(); /* since l_level may be affected */
     return yaz_log_mask_str_x(str, l_level);
 }
 
@@ -564,7 +581,6 @@ int yaz_log_mask_str_x(const char *str, int level)
 {
     const char *p;
 
-    internal_log_init();
     while (*str)
     {
         int negated = 0;