From owner-freebsd-threads@FreeBSD.ORG Tue May 1 13:10:05 2007 Return-Path: X-Original-To: freebsd-threads@hub.freebsd.org Delivered-To: freebsd-threads@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id B6E1E16A400 for ; Tue, 1 May 2007 13:10:05 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [69.147.83.40]) by mx1.freebsd.org (Postfix) with ESMTP id 99CB613C44C for ; Tue, 1 May 2007 13:10:05 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id l41DA5IK016829 for ; Tue, 1 May 2007 13:10:05 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id l41DA5k0016828; Tue, 1 May 2007 13:10:05 GMT (envelope-from gnats) Resent-Date: Tue, 1 May 2007 13:10:05 GMT Resent-Message-Id: <200705011310.l41DA5k0016828@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-threads@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Spencer Minear Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 647D816A402 for ; Tue, 1 May 2007 13:06:03 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [69.147.83.33]) by mx1.freebsd.org (Postfix) with ESMTP id 4ADFA13C46A for ; Tue, 1 May 2007 13:06:03 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.13.1/8.13.1) with ESMTP id l41D633G079650 for ; Tue, 1 May 2007 13:06:03 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.13.1/8.13.1/Submit) id l41D11kJ077800; Tue, 1 May 2007 13:01:01 GMT (envelope-from nobody) Message-Id: <200705011301.l41D11kJ077800@www.freebsd.org> Date: Tue, 1 May 2007 13:01:01 GMT From: Spencer Minear To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.0 Cc: Subject: threads/112300: Memory leak in free_tls within ld-elf.so X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 May 2007 13:10:05 -0000 >Number: 112300 >Category: threads >Synopsis: Memory leak in free_tls within ld-elf.so >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-threads >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue May 01 13:10:05 GMT 2007 >Closed-Date: >Last-Modified: >Originator: Spencer Minear >Release: 6.0 >Organization: Secure Computing Corp >Environment: Found running our modified 6.0 code, but observed on 6.0 and code inspection suggests it is present on Current. >Description: The allocate_tls function in libexec/rtld-elf/rtld.c allocates two memory areas with each call. The free_tls function in the same file only free's one of them wich each call. I.E. there is a memory leak with each thread distruction. The problem gets rather serious for applications like a mail filter based on libmilter. We found the problem with our modified 6.0 based system but it code has not changed even on current so I think it is present in all current released versions fo the code. A static link does not leak, which lead us to the solution in that the code for the same functions in libc (gen/tls.c) does not have the problem. The problem was observed when we used both libpthread and libthr, thus pointin us to the ld-elf code. >How-To-Repeat: Run a program that creates many short lived threads. Following test program shows the problem very quickly. #include #include #include #include #include #include #include #include #include #define INFO_FILE "thread_test_file" #define CREATE_THREAD(ret, func, arg) \ { \ pthread_t tid; \ if ((ret = pthread_create(&tid, NULL, func, (void*)(arg))) == 0) \ ret = pthread_detach(tid); \ } static void* mem_thread(void *arg) { int fd; FILE *fp; pthread_t tid; tid = pthread_self(); if ((fd = open(INFO_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) { fprintf(stderr, "Error opening %s: %s\n", INFO_FILE, strerror(errno)); return(NULL); } printf("File %s created\n", INFO_FILE); if ((fp = fdopen(fd, "w")) == NULL) { printf("Can't fdopen fd %d, %s\n", fd, strerror(errno)); close(fd); return(NULL); } fprintf(fp, "TEST of writing to file"); fflush(fp); fclose(fp); close(fd); return(NULL); } int main(int argc, char **argv, char **envp) { int ret; struct timespec rqtp; int i = 0; printf("Starting\n"); while (1) { CREATE_THREAD(ret, &mem_thread, NULL); if (ret) { perror("Creating thread1"); return -1; } rqtp.tv_sec = 0; rqtp.tv_nsec = 1000 * (i % 25); nanosleep(&rqtp, NULL); i++; } return 0; } >Fix: Copy the logic in the libc/gen/tls.c code and add a call to free the dtv pointer in free_tls within rtld.c. The Diff within in our code base CVS tree is as follows. This seems to fix the problem. I trust you will let us know if we are overlooking something and this fix is not safe. --- rtld.c 3 Jan 2006 20:44:27 -0000 1.4 +++ rtld.c 1 May 2007 12:37:45 -0000 @@ -2733,6 +2733,7 @@ } free((void*) tlsstart); + free(dtv); } #endif >Release-Note: >Audit-Trail: >Unformatted: