From: Ivan Maidanski Date: Sun, 11 Nov 2012 14:57:29 +0000 (+0400) Subject: Fix Win32 GC_write preventing potential infinite recursion at abort X-Git-Tag: gc7_4_0~159 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=608fe467d3d21bb5aa9ed7fd11e360a3d0705b21;p=gc Fix Win32 GC_write preventing potential infinite recursion at abort * 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. --- diff --git a/misc.c b/misc.c index 353cb564..fb56bf39 100644 --- 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