From: Ivan Maidanski Date: Wed, 18 Jul 2012 15:41:43 +0000 (+0400) Subject: Fix GC_err_printf called from atexit hook by duping GC_stderr (Unix) X-Git-Tag: gc7_4_0~249^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8d44d462c88ee3dc66a194ef6758f24bbf8971cc;p=gc Fix GC_err_printf called from atexit hook by duping GC_stderr (Unix) * 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. --- diff --git a/misc.c b/misc.c index e5dbdf79..f32ec4c9 100644 --- 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 + 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;