]> granicus.if.org Git - gc/commitdiff
Fix GC_err_printf called from atexit hook by duping GC_stderr (Unix)
authorIvan Maidanski <ivmai@mail.ru>
Wed, 18 Jul 2012 15:41:43 +0000 (19:41 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 18 Jul 2012 15:41:43 +0000 (19:41 +0400)
* misc.c: Include unistd.h if UNIX_LIKE (or CYGWIN32 or SYMBIAN) for
dup() prototype.
* misc.c (GC_init): Test "GC_FIND_LEAK" environment variable before
that for "GC_LOG_FILE" (since the block for the latter uses
GC_find_leak value).
* misc.c (GC_init): Invoke dup (only if UNIX_LIKE or CYGWIN32 or
SYMBIAN) for GC_stderr and GC_stdout in case of GC_find_leak but
when GC_stdout/err are not redirected to a file (to workaround
outputting to closed stderr/out file descriptor when GC_gcollect
(GC_print_callers) is called from atexit hook); add comment.

misc.c

diff --git a/misc.c b/misc.c
index e5dbdf79203878487fc9c92456a28bf044495fed..f32ec4c945f29be447bc015ad9a791d6921c08b8 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -673,6 +673,8 @@ STATIC void GC_exit_check(void)
 #endif
 
 #if !defined(OS2) && !defined(MACOS) && !defined(MSWIN32) && !defined(MSWINCE)
+# include <unistd.h>
+
   STATIC int GC_stdout = 1;
   STATIC int GC_stderr = 2;
   STATIC int GC_log = 2; /* stderr */
@@ -794,8 +796,14 @@ GC_API void GC_CALL GC_init(void)
           GC_print_stats = 1;
         }
 #     endif
-#     if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(SYMBIAN)
-        {
+#   endif /* !SMALL_CONFIG */
+    if (0 != GETENV("GC_FIND_LEAK")) {
+      GC_find_leak = 1;
+    }
+#   if defined(UNIX_LIKE) || defined(CYGWIN32) || defined(SYMBIAN)
+      {
+        GC_bool need_dup_stdout = GC_find_leak;
+#       ifndef SMALL_CONFIG
           char * file_name = GETENV("GC_LOG_FILE");
 #         ifdef GC_LOG_TO_FILE_ALWAYS
             if (NULL == file_name)
@@ -824,12 +832,26 @@ GC_API void GC_CALL GC_init(void)
               {
                 GC_stdout = log_d;
                 GC_stderr = log_d;
+                need_dup_stdout = FALSE;
               }
             }
           }
+#       endif /* !SMALL_CONFIG */
+        if (need_dup_stdout) {
+          /* In find-leak mode, GC_gcollect (and, thus,         */
+          /* GC_print_callers) could be called inside 'atexit'  */
+          /* hook when stdout and stderr file descriptors are   */
+          /* already closed.   To workaround, we try to         */
+          /* duplicate both of the descriptors.                 */
+          int log_d = dup(GC_stderr);
+          if (log_d != -1)
+            GC_stderr = log_d;
+          log_d = dup(GC_stdout);
+          if (log_d != -1)
+            GC_stdout = log_d;
         }
-#     endif
-#   endif /* !SMALL_CONFIG */
+      }
+#   endif /* UNIX_LIKE || .. */
 #   ifndef NO_DEBUGGING
       if (0 != GETENV("GC_DUMP_REGULARLY")) {
         GC_dump_regularly = TRUE;
@@ -844,9 +866,6 @@ GC_API void GC_CALL GC_init(void)
         }
       }
 #   endif
-    if (0 != GETENV("GC_FIND_LEAK")) {
-      GC_find_leak = 1;
-    }
 #   ifndef SHORT_DBG_HDRS
       if (0 != GETENV("GC_FINDLEAK_DELAY_FREE")) {
         GC_findleak_delay_free = TRUE;