Date: Wed, 14 Dec 2005 17:27:44 +0100 From: Daniel Hartmeier <dhartmei@FreeBSD.org> To: FreeBSD-gnats-submit@FreeBSD.org Cc: Daniel Eischen <deischen@FreeBSD.org> Subject: threads/90392: libc stdio memory leak with pthread Message-ID: <20051214162744.GI17140@insomnia.benzedrine.cx> Resent-Message-ID: <200512141630.jBEGU4kT074202@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 90392 >Category: threads >Synopsis: libc stdio memory leak with pthread >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-threads >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Dec 14 16:30:03 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Daniel Hartmeier >Release: FreeBSD 6.0-STABLE i386 >Organization: >Environment: >Description: Calling sscanf(3) with a '%c' conversion from a multi-threaded (-lpthread) program leaks memory. >How-To-Repeat: Compile and run the following minimal example and observe the leak, e.g. with top(1) $ gcc -o test test.c -lpthread #include <pthread.h> #include <stdio.h> #include <unistd.h> static void *leak(void *p) { const char *s = "foo"; char t[4]; while (1) { (void)sscanf(s, "%3c", t); usleep(1000); } return (NULL); } int main() { pthread_t t; int r; if ((r = pthread_create(&t, NULL, &leak, NULL))) return (1); while (1) usleep(1000); return (0); } >Fix: See /usr/src/lib/libc/stdio/ sscanf.c sscanf() sets up a private FILE object, initializes the thread locking extra with INITEXTRA(), and passes it to __svfscanf(). vfscanf.c __svfscanf() enters case CT_CHAR: with neither LONG nor SUPPRESS flags set, and calls fread(). fread.c fread() uses FLOCKFILE() and FUNLOCKFILE(), which in this case are _flockfile() and _funlockfile(). _flock_stub.c _flockfile() calls _pthread_mutex_lock(2) on the mutex in the extra passed from sscanf(). The mutex was initialized using PTHREAD_MUTEX_INITIALIZER through INITEXTRA(). While it appears to be valid to use the mutex after such initialization (without a pthread_create(2) call), that usage causes delayed initialization which requires a call to pthread_mutex_destroy(2) afterwards. The following patch fixes the leak for me: --- sscanf.c.orig Wed Dec 14 17:16:18 2005 +++ sscanf.c Wed Dec 14 17:16:36 2005 @@ -78,5 +78,6 @@ va_start(ap, fmt); ret = __svfscanf(&f, fmt, ap); va_end(ap); + _pthread_mutex_destroy(&f._extra->fl_mutex); return (ret); } If you grep for other INITEXTRA() calls, those might require a similar fix, possibly justifying an additional macro like FREEEXTRA(). I'm not familiar enough with libc's FILE extra structure nor with pthread_mutex semantics to be perfectly sure. >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20051214162744.GI17140>