No more reachable memory with yaz_deinit_globals
[yaz-moved-to-github.git] / src / log.c
index 265dd77..4edead7 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -103,14 +103,18 @@ static struct {
 
 static unsigned int next_log_bit = YLOG_LAST_BIT<<1; /* first dynamic bit */
 
+static int yaz_log_reopen_flag = 0;
+
 static YAZ_MUTEX log_mutex = 0;
 
-static void yaz_log_lock(void)
+static void yaz_log_open(void);
+
+void yaz_log_lock(void)
 {
     yaz_mutex_enter(log_mutex);
 }
 
-static void yaz_log_unlock(void)
+void yaz_log_unlock(void)
 {
     yaz_mutex_leave(log_mutex);
 }
@@ -150,6 +154,15 @@ void yaz_log_close(void)
     }
 }
 
+void yaz_log_deinit_globals(void)
+{
+    if (log_mutex)
+    {
+        yaz_mutex_destroy(&log_mutex);
+        yaz_log_close();
+    }
+}
+
 void yaz_log_init_file(const char *fname)
 {
     yaz_init_globals();
@@ -169,7 +182,7 @@ void yaz_log_init_file(const char *fname)
         yaz_log_info.type = use_none;  /* NULL name; use no file at all */
         yaz_log_info.l_fname[0] = '\0';
     }
-    yaz_log_reopen();
+    yaz_log_open();
 }
 
 static void rotate_log(const char *cur_fname)
@@ -216,7 +229,7 @@ void yaz_log_init_level(int level)
     if ( (l_level & YLOG_FLUSH) != (level & YLOG_FLUSH) )
     {
         l_level = level;
-        yaz_log_reopen(); /* make sure we set buffering right */
+        yaz_log_open(); /* make sure we set buffering right */
     }
     else
         l_level = level;
@@ -306,6 +319,11 @@ static void yaz_log_open_check(struct tm *tm, int force, const char *filemode)
     if (yaz_log_info.type != use_file)
         return;
 
+    if (yaz_log_reopen_flag)
+    {
+        force = 1;
+        yaz_log_reopen_flag = 0;
+    }
     if (*yaz_log_info.l_fname)
     {
         strftime(new_filename, sizeof(new_filename)-1, yaz_log_info.l_fname,
@@ -332,13 +350,14 @@ static void yaz_log_open_check(struct tm *tm, int force, const char *filemode)
 #ifdef WIN32
         yaz_log_close();
 #endif
-        new_file = fopen(cur_filename, filemode);
+        if (!strncmp(cur_filename, "fd=", 3))
+            new_file = fdopen(atoi(cur_filename + 3), filemode);
+        else
+            new_file = fopen(cur_filename, filemode);
         if (new_file)
         {
             yaz_log_close();
             yaz_log_info.log_file = new_file;
-            if (l_level & YLOG_FLUSH)
-                setvbuf(yaz_log_info.log_file, 0, _IONBF, 0);
         }
         else
         {
@@ -367,9 +386,13 @@ static void yaz_log_do_reopen(const char *filemode)
     yaz_log_unlock();
 }
 
-
 void yaz_log_reopen()
 {
+    yaz_log_reopen_flag = 1;
+}
+
+static void yaz_log_open()
+{
     yaz_log_do_reopen("a");
 }
 
@@ -384,7 +407,8 @@ static void yaz_strftime(char *dst, size_t sz,
     strftime(dst, sz, fmt, tm);
 }
 
-static void yaz_log_to_file(int level, const char *log_message)
+static void yaz_log_to_file(int level, const char *fmt, va_list ap,
+                            const char *error_cp)
 {
     FILE *file;
     time_t ti = time(0);
@@ -446,9 +470,12 @@ static void yaz_log_to_file(int level, const char *log_message)
                 strcat(tid, " ");
         }
 
-        fprintf(file, "%s%s%s%s %s%s\n", tbuf, yaz_log_info.l_prefix,
-                tid, flags, yaz_log_info.l_prefix2,
-                log_message);
+        fprintf(file, "%s%s%s%s %s", tbuf, yaz_log_info.l_prefix,
+                tid, flags, yaz_log_info.l_prefix2);
+        vfprintf(file, fmt, ap);
+        if (error_cp)
+            fprintf(file, " [%s]", error_cp);
+        fputs("\n", file);
         if (l_level & YLOG_FLUSH)
             fflush(file);
     }
@@ -458,40 +485,43 @@ static void yaz_log_to_file(int level, const char *log_message)
 void yaz_log(int level, const char *fmt, ...)
 {
     va_list ap;
-    char buf[4096];
     FILE *file;
     int o_level = level;
+    char *error_cp = 0, error_buf[128];
 
+    if (o_level & YLOG_ERRNO)
+    {
+        yaz_strerror(error_buf, sizeof(error_buf));
+        error_cp = error_buf;
+    }
     yaz_init_globals();
     if (!(level & l_level))
         return;
     va_start(ap, fmt);
 
-    /* 30 is enough for our 'rest of output' message */
-    yaz_vsnprintf(buf, sizeof(buf)-30, fmt, ap);
-    if (strlen(buf) >= sizeof(buf)-31)
-        strcat(buf, " [rest of output omitted]");
-
-    if (o_level & YLOG_ERRNO)
+    file = yaz_log_file();
+    if (start_hook_func || hook_func || end_hook_func)
     {
-        size_t remain = sizeof(buf) - strlen(buf);
-        if (remain > 100) /* reasonable minimum space for error */
-        {
-            strcat(buf, " [");
-            yaz_strerror(buf+strlen(buf), remain-5); /* 5 due to extra [] */
-            strcat(buf, "]");
-        }
+        char buf[1024];
+        /* 30 is enough for our 'rest of output' message */
+        yaz_vsnprintf(buf, sizeof(buf)-30, fmt, ap);
+        if (strlen(buf) >= sizeof(buf)-31)
+            strcat(buf, " [rest of output omitted]");
+        if (start_hook_func)
+            (*start_hook_func)(o_level, buf, start_hook_info);
+        if (hook_func)
+            (*hook_func)(o_level, buf, hook_info);
+        if (file)
+            yaz_log_to_file(level, fmt, ap, error_cp);
+        if (end_hook_func)
+            (*end_hook_func)(o_level, buf, end_hook_info);
     }
-    va_end (ap);
-    if (start_hook_func)
-        (*start_hook_func)(o_level, buf, start_hook_info);
-    if (hook_func)
-        (*hook_func)(o_level, buf, hook_info);
-    file = yaz_log_file();
-    if (file)
-        yaz_log_to_file(level, buf);
-    if (end_hook_func)
-        (*end_hook_func)(o_level, buf, end_hook_info);
+    else
+    {
+        if (file)
+            yaz_log_to_file(level, fmt, ap, error_cp);
+    }
+    va_end(ap);
 }
 
 void yaz_log_time_format(const char *fmt)
@@ -577,6 +607,8 @@ int yaz_log_mask_str(const char *str)
     return yaz_log_mask_str_x(str, l_level);
 }
 
+/* this function is called by yaz_log_init_globals & yaz_init_globals
+   and, thus, may not call any of them indirectly */
 int yaz_log_mask_str_x(const char *str, int level)
 {
     const char *p;