From: mycroft@hal.gnu.ai.mit.edu (Charles Hannum)
Newsgroups: comp.unix.bsd
Subject: Memory leak in kvm_getprocs() and top 3.0
Date: 7 Jan 93 02:35:49 GMT
Organization: MIT Artificial Intelligence Lab
NNTP-Posting-Host: hal.gnu.ai.mit.edu


Here are two sets of patches.  The first fixes a memory leak in
kvm_getprocs(), and the second is to convent m_bsd44.c to m_386bsd.c,
in the top 3.0 distribution.

Note that while I've tried to take advantage of virtual memory
metering, this is not yet implemented in 386BSD.  I'm also not entirely
certain why the resident size always shows up as `0'.  I'll post a
patch when I decide to think about it again.

-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
*** /usr/src/lib/libutil/kvm.c~	Fri Nov 27 21:16:35 1992
--- /usr/src/lib/libutil/kvm.c	Wed Jan  6 20:32:34 1993
***************
*** 99,105 ****
  /*
   * state
   */
! static	struct kinfo_proc *kvmprocbase, *kvmprocptr;
  static	int kvmnprocs;
  /*
   * u. buffer
--- 99,105 ----
  /*
   * state
   */
! static	struct kinfo_proc *kvmprocbase = NULL, *kvmprocptr;
  static	int kvmnprocs;
  /*
   * u. buffer
***************
*** 406,411 ****
--- 406,413 ----
  			return (-1);
  		}
  		copysize = ret;
+ 		if (kvmprocbase)
+ 			free(kvmprocbase);
  		if ((kvmprocbase = (struct kinfo_proc *)malloc(copysize)) 
  		     == NULL) {
  			seterr("out of memory");
-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----

-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
*** m_bsd44.c	Sat May  9 15:09:54 1992
--- m_386bsd.c	Wed Jan  6 21:28:02 1993
***************
*** 2,17 ****
   * top - a top users display for Unix
   *
!  * SYNOPSIS:  For a pre-release 4.4BSD system
!  *	      Note memory statistisc and process sizes could be wrong,
!  *	      by ps gets them wrong too...
   *
   * DESCRIPTION:
!  * This is the machine-dependent module for BSD4.4 
!  * Works for:
!  *	hp300
   *
!  * LIBS: -lkvm
!  *
!  * AUTHOR:  Christos Zoulas <christos@ee.cornell.edu>
   */
  
--- 2,13 ----
   * top - a top users display for Unix
   *
!  * SYNOPSIS:  For 386BSD 0.1
   *
   * DESCRIPTION:
!  * This is the machine-dependent module for 386BSD
   *
!  * AUTHOR:  Charles Hannum <mycroft@ai.mit.edu>
!  *	    based on m_bsd44.c, by
!  *	    Christos Zoulas <christos@ee.cornell.edu>
   */
  
***************
*** 27,30 ****
--- 23,27 ----
  #include <sys/kinfo.h>
  #include <sys/kinfo_proc.h>
+ #include <sys/vmmeter.h>
  #ifdef notyet
  #define time __time
***************
*** 45,50 ****
  #include "machine.h"
  
! #define VMUNIX	"/vmunix"
! #define KMEM	"/dev/kmem"
  #define MEM	"/dev/mem"
  #ifdef DOSWAP
--- 42,47 ----
  #include "machine.h"
  
! #define VMUNIX	"/386bsd"
! #define KMEM	NULL
  #define MEM	"/dev/mem"
  #ifdef DOSWAP
***************
*** 79,82 ****
--- 76,80 ----
  #define X_HZ		2
  #define X_AVENRUN	3
+ #define X_TOTAL		4
  
  static struct nlist nlst[] = {
***************
*** 85,88 ****
--- 83,87 ----
      { "_hz" },			/* 2 */
      { "_averunnable" },		/* 3 */
+     { "_total" },		/* 4 */
      { 0 }
  };
***************
*** 111,116 ****
  
  
- static kvm_t *kd;
- 
  /* values that we stash away in _init and use in later routines */
  
--- 110,113 ----
***************
*** 185,194 ****
      register int pagesize;
  
!     if ((kd = kvm_open(VMUNIX, MEM, SWAP, O_RDONLY, "kvm_open")) == NULL)
  	return -1;
  
- 
      /* get the list of symbols we want to access in the kernel */
!     (void) kvm_nlist(kd, nlst);
      if (nlst[0].n_type == 0)
      {
--- 182,190 ----
      register int pagesize;
  
!     if (kvm_openfiles(VMUNIX, KMEM, SWAP) == -1)
  	return -1;
  
      /* get the list of symbols we want to access in the kernel */
!     (void) kvm_nlist(nlst);
      if (nlst[0].n_type == 0)
      {
***************
*** 302,307 ****
  	int size;
  
! 	/* get total -- systemwide main memory usage structure */
! 	getkerninfo(KINFO_METER, &total, &size, 0);
  	/* convert memory stats to Kbytes */
  	memory_stats[0] = -1;
--- 298,303 ----
  	int size;
  
!         (void) getkval(nlst[X_TOTAL].n_value, (int *)(&total), sizeof(total),
! 		       nlst[X_TOTAL].n_name);
  	/* convert memory stats to Kbytes */
  	memory_stats[0] = -1;
***************
*** 343,354 ****
  
      
!     pbase = kvm_getprocs(kd, KINFO_PROC_ALL, 0, &nproc);
!     if (nproc > onproc)
! 	pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
! 		* (onproc = nproc));
!     if (pref == NULL || pbase == NULL) {
! 	(void) fprintf(stderr, "top: Out of memory.\n");
  	quit(23);
      }
      /* get a pointer to the states summary array */
      si->procstates = process_states;
--- 339,355 ----
  
      
!     if ((nproc = kvm_getprocs(KINFO_PROC_ALL, 0)) == -1) {
!         (void) fprintf(stderr, "top: kvm_getprocs() failed: %s\n", kvm_geterr());
! 	quit(23);
!     }
! 
!     if (pref)
!         free(pref);
! 
!     if ((pref = (struct kinfo_proc **) malloc(sizeof(struct kinfo_proc *) * nproc)) ==  NULL) {
!         (void) fprintf(stderr, "top: out of memory\n");
  	quit(23);
      }
+ 
      /* get a pointer to the states summary array */
      si->procstates = process_states;
***************
*** 365,369 ****
      memset((char *)process_states, 0, sizeof(process_states));
      prefp = pref;
!     for (pp = pbase, i = 0; i < nproc; pp++, i++)
      {
  	/*
--- 366,370 ----
      memset((char *)process_states, 0, sizeof(process_states));
      prefp = pref;
!     for (kvm_setproc(); pp = (struct kinfo_proc *) kvm_nextproc();)
      {
  	/*
***************
*** 520,524 ****
  
  {
!     if (kvm_read(kd, offset, (char *) ptr, size) != size)
      {
  	if (*refstr == '!')
--- 521,525 ----
  
  {
!     if (kvm_read((void *) offset, (char *) ptr, size) != size)
      {
  	if (*refstr == '!')
***************
*** 562,575 ****
  proc_compare(pp1, pp2)
  
! struct kinfo_proc **pp1;
! struct kinfo_proc **pp2;
  
  {
!     register struct kinfo_proc *p1;
!     register struct kinfo_proc *p2;
      register int result;
      register pctcpu lresult;
  
-     /* remove one level of indirection */
      p1 = *pp1;
      p2 = *pp2;
--- 563,573 ----
  proc_compare(pp1, pp2)
  
! struct kinfo_proc **pp1, **pp2;
  
  {
!     register struct kinfo_proc *p1, *p2;
      register int result;
      register pctcpu lresult;
  
      p1 = *pp1;
      p2 = *pp2;
-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----snip-----8<-----
-- 
 \  /   Charles Hannum, mycroft@ai.mit.edu
 /\ \   PGP public key available on request.  MIME, AMS, NextMail accepted.
Scheme  White heterosexual atheist male (WHAM) pride!
Newsgroups: comp.unix.bsd