From: Jay Satiro Date: Wed, 17 Feb 2021 22:46:16 +0000 (-0500) Subject: memdebug: close debug logfile explicitly on exit X-Git-Tag: curl-7_76_0~131 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=eb36c03e83ecc110bb14480fca911ef45621f24a;p=thirdparty%2Fcurl.git memdebug: close debug logfile explicitly on exit - Use atexit to register a dbg cleanup function that closes the logfile. LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected on exit so the logfile must be closed explicitly or data could be lost. Though _exit() does not call atexit handlers such as this, LSAN's call to _exit() comes after the atexit handlers are called. Prior to this change the logfile was not explicitly closed so it was possible that if LSAN detected a leak and called _exit (which does not flush or close files like exit) then the logfile could be missing data. That could then cause curl's memanalyze to report false leaks (eg a malloc was recorded to the logfile but the corresponding free was discarded from the buffer instead of written to the logfile, then memanalyze reports that as a leak). Ref: https://github.com/google/sanitizers/issues/1374 Bug: https://github.com/curl/curl/pull/6591#issuecomment-780396541 Closes https://github.com/curl/curl/pull/6620 --- diff --git a/lib/memdebug.c b/lib/memdebug.c index 0aba6ef6ba..8b763577bb 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -55,9 +55,24 @@ struct memdebug { */ FILE *curl_dbg_logfile = NULL; +static bool registered_cleanup = FALSE; /* atexit registered cleanup */ static bool memlimit = FALSE; /* enable memory limit */ static long memsize = 0; /* set number of mallocs allowed */ +/* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected + on exit so the logfile must be closed explicitly or data could be lost. + Though _exit() does not call atexit handlers such as this, LSAN's call to + _exit() comes after the atexit handlers are called. curl/curl#6620 */ +static void curl_dbg_cleanup(void) +{ + if(curl_dbg_logfile && + curl_dbg_logfile != stderr && + curl_dbg_logfile != stdout) { + fclose(curl_dbg_logfile); + } + curl_dbg_logfile = NULL; +} + /* this sets the log file name */ void curl_dbg_memdebug(const char *logname) { @@ -72,6 +87,8 @@ void curl_dbg_memdebug(const char *logname) setbuf(curl_dbg_logfile, (char *)NULL); #endif } + if(!registered_cleanup) + registered_cleanup = !atexit(curl_dbg_cleanup); } /* This function sets the number of malloc() calls that should return