]> granicus.if.org Git - gc/commitdiff
Fix Win32 GC_write preventing potential infinite recursion at abort
authorIvan Maidanski <ivmai@mail.ru>
Sun, 11 Nov 2012 14:57:29 +0000 (18:57 +0400)
committerIvan Maidanski <ivmai@mail.ru>
Sun, 11 Nov 2012 15:26:24 +0000 (19:26 +0400)
* misc.c (GC_write): Define "inside_write" static variable (only
for Win32 and only if THREADS and GC_ASSERTIONS or
GC_PRINT_VERBOSE_STATS); if this variable is set then just return,
set this variable if GC_write_disabled or GC_log is
INVALID_HANDLE_VALUE just before ABORT call (to prevent infinite
recursion).
* misc.c (GC_default_on_abort): Do not call WRITE if GC_write_disabled
(only for Win32 and only if THREADS and GC_ASSERTIONS) to prevent
abort in GC_write.

misc.c

diff --git a/misc.c b/misc.c
index 353cb564fefcfb8aa7b15d58fb7d918b391ad02b..fb56bf39e26a1557e8a6e109cdf5b54ded550e68 100644 (file)
--- a/misc.c
+++ b/misc.c
@@ -1310,11 +1310,22 @@ GC_API void GC_CALL GC_enable_incremental(void)
   {
       BOOL tmp;
       DWORD written;
+#     if (defined(THREADS) && defined(GC_ASSERTIONS)) \
+         || !defined(GC_PRINT_VERBOSE_STATS)
+        static GC_bool inside_write = FALSE;
+                        /* to prevent infinite recursion at abort.      */
+        if (inside_write)
+          return -1;
+#     endif
+
       if (len == 0)
           return 0;
       IF_NEED_TO_LOCK(EnterCriticalSection(&GC_write_cs));
-#     ifdef THREADS
-        GC_ASSERT(!GC_write_disabled);
+#     if defined(THREADS) && defined(GC_ASSERTIONS)
+        if (GC_write_disabled) {
+          inside_write = TRUE;
+          ABORT("Assertion failure: GC_write called with write_disabled");
+        }
 #     endif
       if (GC_log == INVALID_HANDLE_VALUE) {
           IF_NEED_TO_LOCK(LeaveCriticalSection(&GC_write_cs));
@@ -1324,8 +1335,10 @@ GC_API void GC_CALL GC_enable_incremental(void)
         /* Ignore open log failure if the collector is built with       */
         /* print_stats always set on.                                   */
 #       ifndef GC_PRINT_VERBOSE_STATS
-          if (GC_log == INVALID_HANDLE_VALUE)
+          if (GC_log == INVALID_HANDLE_VALUE) {
+            inside_write = TRUE;
             ABORT("Open of log file failed");
+          }
 #       endif
       }
       tmp = WriteFile(GC_log, buf, (DWORD)len, &written, NULL);
@@ -1552,8 +1565,15 @@ GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void)
       /* Avoid calling GC_err_printf() here, as GC_on_abort() could be  */
       /* called from it.  Note 1: this is not an atomic output.         */
       /* Note 2: possible write errors are ignored.                     */
-      if (WRITE(GC_stderr, (void *)msg, strlen(msg)) >= 0)
-        (void)WRITE(GC_stderr, (void *)("\n"), 1);
+
+#     if defined(THREADS) && defined(GC_ASSERTIONS) \
+         && (defined(MSWIN32) || defined(MSWINCE))
+        if (!GC_write_disabled)
+#     endif
+      {
+        if (WRITE(GC_stderr, (void *)msg, strlen(msg)) >= 0)
+          (void)WRITE(GC_stderr, (void *)("\n"), 1);
+      }
     }
 
 #   ifndef NO_DEBUGGING