Re: memory leaks from calls to opendir and fopen

"Saurabh Desai" <[email protected]> Wed, 24 Jul 2002 18:17:30 -0600
Newsgroups gmane.linux.ngpt.user
Message-ID <[email protected]>

The pthread mutex created by certain glibc functions didn't get freed
properly
by ngpt and that causes memory leaks.  Here is a patch for ngpt-2.0.0
release
to fix this problem. Thank you for providing a testcase and reporting this
bug.

(See attached file: ngpt-2.0.0-1.diff)

Thanks,
- - - - -
Saurabh Desai
POSIX Threading for Linux
IBM  Linux Technology Center
e-mail: [email protected] OR [email protected]
phone: 512-838-2655, T/L: 678-2655
http://oss.software.ibm.com/developerworks/opensource/pthreads



Nathan Falk/Poughkeepsie/IBM@[email protected] on
07/24/2002 10:29:49 AM

Sent by:    [email protected]


To:    [email protected]
cc:
Subject:    [pthreads-users] memory leaks from calls to opendir and fopen


I noticed considerable growth in a daemon (so much that the system ran out
of virtual memory after the daemon was running for about a day and a half),
and tried to track it down.  I didn't have much like finding memory tools
that would work with my app.  I suspect that's partly due to ngpt.  What I
ended up doing was writing the get_vsize() function below to take snapshots
of how much memory my process has allocated.  I narrowed the leaks down to
calls to opendir() and fopen() (there may be others).

Thinking there might be a bug in glibc (but doubting it), I wrote a simple,
stand-alone program to demonstrate the problem.  I couldn't recreate it.
Then I thought to link in pthreads, and that's when the test program
exhibited the same behavior as my app.  I brought the source over to a
vanilla RH 7.2 system (2.4.7 kernel, LinuxThreads) and re-compiled it.  No
growth.

I'm not sure where to go from here.  It seems like ngpt is the culprit, and
it seems to be from memory allocated when open() is called.  Compiling and
running the program below (be sure to use -lpthread) on a system with ngpt
versus a system without ngpt will demonstrate the growth on the system with
ngpt.


#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <pthread.h>

unsigned int
get_vsize()
{
   int procfile;
   char path_to_procfile[16]; /* just has to hold "/proc/nnnnn/stat" */
   char stat_buffer[256];  /* should be enough */
   int my_pid = getpid();
   int vsize_pos = 22; /* the field we want is 22nd */
   int ndx;
   unsigned int vsize;
   char *ptr = NULL;

   sprintf(path_to_procfile, "/proc/%d/stat", my_pid);
   procfile = open(path_to_procfile, O_RDONLY);
   if (!procfile) return(0);

   ndx = read(procfile, stat_buffer, sizeof(stat_buffer)-1);
   stat_buffer[ndx] = '\0';
   close(procfile);

   ptr = &stat_buffer[0];
   printf("%s\n", stat_buffer);
   while (vsize_pos > 0) {
      ptr = strchr(ptr, ' ');
      ptr++;
      if (!ptr) return(0);
/*    printf("%d: %s\n", vsize_pos, ptr); */
      vsize_pos--;
   }
   sscanf(ptr, "%u", &vsize);
/* printf("%u\n", vsize); */
   return vsize;
}


int
main()
{
   unsigned int vsize;
   DIR *dirp = NULL;
   int count = 20;

   while(count > 0) {

   vsize = get_vsize();
   printf("vsize  (1) = %u\n", vsize);

   dirp = opendir("/proc");
   if (!dirp) return(0);

   vsize = get_vsize();
   printf("vsize (2)= %u\n", vsize);

   closedir(dirp);

   vsize = get_vsize();
   printf("vsize (3) = %u\n", vsize);

   sleep(15);
   count--;
   } /* end while */
}

Thanks,

Nate Falk
RS/6000 SP Workload Management/LoadLeveler
845-433-8162 (T/L: 293-8162)



_______________________________________________
pthreads-users mailing list
[email protected]
http://www-124.ibm.com/developerworks/oss/mailman/listinfo/pthreads-users
ngpt-2.0.0-1.diff (application/octet-stream, 870 B)
diff -Naur ngpt-2.0.0/pthread.c ngpt-2.0.0-destroy/pthread.c
--- ngpt-2.0.0/pthread.c	Fri Jun 21 12:18:32 2002
+++ ngpt-2.0.0-destroy/pthread.c	Wed Jul 24 16:50:43 2002
@@ -979,10 +979,15 @@
         return EINVAL;
     pth_acquire_lock(&((pth_mutex_t *)*mutex)->mx_lock); 
     if (((pth_mutex_t *)*mutex)->mx_state & PTH_MUTEX_LOCKED) {
+	if (((pth_mutex_t *)*mutex)->mx_owner == pth_get_current()) {
+	    pth_release_lock(&((pth_mutex_t *)*mutex)->mx_lock); 
+	    pthread_mutex_unlock(mutex);
+	} else {
+	    pth_release_lock(&((pth_mutex_t *)*mutex)->mx_lock); 
+	    return EBUSY;
+	}
+    } else
 	pth_release_lock(&((pth_mutex_t *)*mutex)->mx_lock); 
-	return EBUSY;
-    }
-    pth_release_lock(&((pth_mutex_t *)*mutex)->mx_lock); 
     for (i = 0; i < mutex_index + 1; i++) {
 	if ((pth_mutex_t *)*mutex == (pth_mutex_t *)&(init_mutex[i])) 
 	    return OK;