threads/90392: libc stdio memory leak with pthread

Daniel Hartmeier dhartmei at
Wed Dec 14 08:30:05 PST 2005

>Number:         90392
>Category:       threads
>Synopsis:       libc stdio memory leak with pthread
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-threads
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Dec 14 16:30:03 GMT 2005
>Originator:     Daniel Hartmeier
>Release:        FreeBSD 6.0-STABLE i386
	Calling sscanf(3) with a '%c' conversion from a multi-threaded
	(-lpthread) program leaks memory.

	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);
	return (NULL);

int main()
	pthread_t t;
	int r;

	if ((r = pthread_create(&t, NULL, &leak, NULL)))
		return (1);
	while (1)
	return (0);

	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

	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);
+       _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

	I'm not familiar enough with libc's FILE extra structure nor
	with pthread_mutex semantics to be perfectly sure.


More information about the freebsd-threads mailing list