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>
index | next in thread | raw e-mail
>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:
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20051214162744.GI17140>
