Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Feb 2001 00:53:33 +0100 (CET)
From:      Martin Butkus <mb@bagheera.thgwf.de>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/24857: File descriptor leak and frequent crashes of rpc.rstatd [PATCH]
Message-ID:  <200102042353.f14NrX609141@bagheera.dyndns.org>

next in thread | raw e-mail | index | archive | help

>Number:         24857
>Category:       bin
>Synopsis:       File descriptor leak and frequent crashes of rpc.rstatd [PATCH]
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Feb 04 16:00:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Martin Butkus
>Release:        FreeBSD 4.2-STABLE i386
>Organization:
TU Braunschweig, Germany
>Environment:

- several i386 boxen running a recently cvsupped FreeBSD 4.2-STABLE: 

rstat_proc.c:
     $FreeBSD: src/libexec/rpc.rstatd/rstat_proc.c,v 1.14 1999/08/28 00:09:54 peter Exp $

rstatd.c:
     $FreeBSD: src/libexec/rpc.rstatd/rstatd.c,v 1.8 1999/08/28 00:09:54 peter Exp $

- an i386 server running an old 3.5-STABLE:

rstat_proc.c:
     $FreeBSD: src/libexec/rpc.rstatd/rstat_proc.c,v 1.14 1999/08/28 00:09:54 peter Exp $

rstatd.c:
     $FreeBSD: src/libexec/rpc.rstatd/rstatd.c,v 1.7.2.1 1999/08/29 15:03:49 peter Exp $


>Description:

I run rpc.rstatd on several FreeBSD boxes. A monitoring
process polls every machine every five minutes.  Running 
rstatd from inetd gave me bogus results (network activity was 
reported way too high, etc.) so I resorted to running rstatd 
standalone. 

However, when run standalone, it crashed frequently, and I also 
discovered a file descriptor leak.

I have observed that:

1) rpc.rstatd opens /dev/mem and /dev/kmem multiple times 
   until running out of file descriptors.
2) rpc.rstatd often crashes within 24 hours 

I have found and fixed the file descriptor leak but the crashes 
continued. I have then backtraced a core dump and found that 
updatestat() had been called from within itself. 

I figured there was a timing problem, i.e. updatestat() was 
running while there was still an alarm pending.
Since updatestat() is the signal handler for SIGALRM, this 
triggered the recursive call of updatestat().

I have therefore added an "alarm(0)" call at the beginning of 
updatestat() in order to clear any pending alarms. 
With these two modification, rpc.rstatd has been running 
on all my machines flawlessly and continuously for more than 
a week now.

>How-To-Repeat:
	
This is difficult because on my network, rstatd is polled
frequently (every 5 minutes) by a monitoring program.  I don't know
if this triggers the bug(s). It could well be possible.  

The following actions have triggered the bug at my site:

	ad 1) run rpc.rstatd standalone
	   # /usr/libexec/rpc.rstatd
	   
	   wait long enough :(. For me, an rstatd crashed after 
 	   about 24 hours.

	
	ad 2) run rpc.rstatd standalone

	   # /usr/libexec/rpc.rstatd

	   Wait a few minutes, then do an 
	
	   # fstat

	   and see rstatd having opened /dev/mem several times.

	   Wait a few hours more and watch the file descriptor 
	   table run full :(.

>Fix:

This patch (against rstat_proc.c ver 1.14) has made rstatd run stable 
for me:

--- libexec/rpc.rstatd/rstat_proc.c.orig	Tue Jan 16 16:27:09 2001
+++ libexec/rpc.rstatd/rstat_proc.c	Sat Jan 20 14:47:32 2001
@@ -99,7 +99,7 @@
 
 void updatestat();
 static stat_is_init = 0;
-static kvm_t *kd;
+static kvm_t *kd = NULL;
 
 static int	cp_time_xlat[RSTAT_CPUSTATES] = { CP_USER, CP_NICE, CP_SYS,
 							CP_IDLE };
@@ -203,15 +203,20 @@
 #ifdef DEBUG
                 fprintf(stderr, "about to closedown\n");
 #endif
-                if (from_inetd)
+                if (from_inetd) {
+			kvm_close(kd);
                         exit(0);
+		}
                 else {
                         stat_is_init = 0;
                         return;
                 }
 	}
+
+	alarm(0);
 	sincelastreq++;
 
+
 	mib[0] = CTL_KERN;
 	mib[1] = KERN_CLOCKRATE;
 	len = sizeof clockrate;
@@ -315,7 +320,9 @@
 
 	int en;
 
-	if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) {
+
+	if (kd == NULL &&
+            (kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) {
 		syslog(LOG_ERR, "rpc.rstatd, %s", errbuf);
 		exit(1);
 	}

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200102042353.f14NrX609141>