Clarify how one is supposed to use the pointers returned by getutentries()

(the utmpentry.c code), specifically with respect to who owns them and
when to free them. Now they're owned by utmpentry.c, only. Abolish the
freeutentries() function, which was the wrong abstraction; add instead
endutentries(), which flushes out the internally managed memory.

Update callers as necessary. Some (e.g. talkd) had been leaking memory;
others (e.g. syslogd) had been accidentally freeing and reloading utmp
more often than necessary. There are a couple untidy bits in users and
rwhod that someone should look after sometime, maybe.

Fixes PR bin/35131, which was about talkd's memory leak.
This commit is contained in:
dholland 2008-07-13 20:07:48 +00:00
parent 96f87739b6
commit 16e3bec279
8 changed files with 44 additions and 56 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dm.c,v 1.24 2007/12/15 19:44:40 perry Exp $ */
/* $NetBSD: dm.c,v 1.25 2008/07/13 20:07:48 dholland Exp $ */
/*
* Copyright (c) 1987, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1987, 1993\n\
#if 0
static char sccsid[] = "@(#)dm.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: dm.c,v 1.24 2007/12/15 19:44:40 perry Exp $");
__RCSID("$NetBSD: dm.c,v 1.25 2008/07/13 20:07:48 dholland Exp $");
#endif
#endif /* not lint */
@ -247,15 +247,10 @@ load(void)
int
users(void)
{
static struct utmpentry *ohead = NULL;
struct utmpentry *ep;
int nusers;
nusers = getutentries(NULL, &ep);
if (ep != ohead) {
freeutentries(ep);
ohead = ep;
}
return nusers;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: comsat.c,v 1.36 2007/05/03 15:09:41 christos Exp $ */
/* $NetBSD: comsat.c,v 1.37 2008/07/13 20:07:48 dholland Exp $ */
/*
* Copyright (c) 1980, 1993
@ -36,7 +36,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
#if 0
static char sccsid[] = "from: @(#)comsat.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: comsat.c,v 1.36 2007/05/03 15:09:41 christos Exp $");
__RCSID("$NetBSD: comsat.c,v 1.37 2008/07/13 20:07:48 dholland Exp $");
#endif
#endif /* not lint */
@ -82,7 +82,6 @@ __RCSID("$NetBSD: comsat.c,v 1.36 2007/05/03 15:09:41 christos Exp $");
static int logging;
static int debug;
static char hostname[MAXHOSTNAMELEN + 1];
static time_t utmpmtime; /* last modification time for utmp/x */
static int nutmp;
static struct utmpentry *utmp = NULL;
static time_t lastmsgtime;
@ -173,9 +172,6 @@ onalrm(int signo)
static void
checkutmp(void)
{
struct stat statbf;
time_t newtime = 0;
if (!needupdate)
return;
needupdate = 0;
@ -183,21 +179,7 @@ checkutmp(void)
if (time(NULL) - lastmsgtime >= MAXIDLE)
exit(0);
(void)alarm((u_int)15);
#ifdef SUPPORT_UTMP
if (stat(_PATH_UTMP, &statbf) != -1)
if (statbf.st_mtime > newtime)
newtime = statbf.st_mtime;
#endif
#ifdef SUPPORT_UTMPX
if (stat(_PATH_UTMPX, &statbf) != -1)
if (statbf.st_mtime > newtime)
newtime = statbf.st_mtime;
#endif
if (newtime > utmpmtime) {
freeutentries(utmp);
nutmp = getutentries(NULL, &utmp);
utmpmtime = newtime;
}
nutmp = getutentries(NULL, &utmp);
}
static void

View File

@ -1,4 +1,4 @@
/* $NetBSD: vmstat.c,v 1.70 2008/02/11 03:51:17 dyoung Exp $ */
/* $NetBSD: vmstat.c,v 1.71 2008/07/13 20:07:48 dholland Exp $ */
/*-
* Copyright (c) 1983, 1989, 1992, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94";
#endif
__RCSID("$NetBSD: vmstat.c,v 1.70 2008/02/11 03:51:17 dyoung Exp $");
__RCSID("$NetBSD: vmstat.c,v 1.71 2008/07/13 20:07:48 dholland Exp $");
#endif /* not lint */
/*
@ -680,15 +680,10 @@ static int
ucount(void)
{
static int onusers = -1;
static struct utmpentry *oehead = NULL;
int nusers = 0;
struct utmpentry *ehead;
nusers = getutentries(NULL, &ehead);
if (oehead != ehead) {
freeutentries(oehead);
oehead = ehead;
}
if (nusers != onusers) {
if (nusers == 1)

View File

@ -1,4 +1,4 @@
/* $NetBSD: users.c,v 1.13 2004/01/05 23:23:37 jmmv Exp $ */
/* $NetBSD: users.c,v 1.14 2008/07/13 20:07:48 dholland Exp $ */
/*
* Copyright (c) 1980, 1987, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1987, 1993\n\
#if 0
static char sccsid[] = "@(#)users.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: users.c,v 1.13 2004/01/05 23:23:37 jmmv Exp $");
__RCSID("$NetBSD: users.c,v 1.14 2008/07/13 20:07:48 dholland Exp $");
#endif /* not lint */
#include <sys/types.h>
@ -79,6 +79,14 @@ main(argc, argv)
if (ncnt == 0)
return 0;
/*
* XXX the utmp list belongs to getutentries and we shouldn't
* sort it in place. Since we don't call endutentries and we
* don't call getutentries again it doesn't matter, but it's
* untidy. Maybe give getutentries a sort function? It has to
* sort anyway if it's merging utmp and utmpx data.
*/
from = ehead;
ehead = NULL;
while (from != NULL) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: utmpentry.c,v 1.14 2008/04/28 20:24:15 martin Exp $ */
/* $NetBSD: utmpentry.c,v 1.15 2008/07/13 20:07:48 dholland Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: utmpentry.c,v 1.14 2008/04/28 20:24:15 martin Exp $");
__RCSID("$NetBSD: utmpentry.c,v 1.15 2008/07/13 20:07:48 dholland Exp $");
#endif
#include <sys/stat.h>
@ -157,23 +157,24 @@ setup(const char *fname)
#endif
void
freeutentries(struct utmpentry *ep)
endutentries(void)
{
struct utmpentry *ep;
#ifdef SUPPORT_UTMP
timespecclear(&utmptime);
#endif
#ifdef SUPPORT_UTMPX
timespecclear(&utmpxtime);
#endif
if (ep == ehead) {
ehead = NULL;
numutmp = 0;
}
ep = ehead;
while (ep) {
struct utmpentry *sep = ep;
ep = ep->next;
free(sep);
}
ehead = NULL;
numutmp = 0;
}
int

View File

@ -1,4 +1,4 @@
/* $NetBSD: utmpentry.h,v 1.6 2008/04/28 20:24:15 martin Exp $ */
/* $NetBSD: utmpentry.h,v 1.7 2008/07/13 20:07:49 dholland Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@ -60,5 +60,17 @@ struct utmpentry {
extern int maxname, maxline, maxhost;
extern int etype;
/*
* getutentries provides a linked list of struct utmpentry and returns
* the number of entries. The first argument, if not null, names an
* alternate utmp(x) file to look in.
*
* The memory returned by getutentries belongs to getutentries. The
* list returned (or elements of it) may be returned again later if
* utmp hasn't changed in the meantime.
*
* endutentries clears and frees the cached data.
*/
int getutentries(const char *, struct utmpentry **);
void freeutentries(struct utmpentry *);
void endutentries(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rwhod.c,v 1.35 2007/12/15 19:44:56 perry Exp $ */
/* $NetBSD: rwhod.c,v 1.36 2008/07/13 20:07:49 dholland Exp $ */
/*
* Copyright (c) 1983, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\n\
#if 0
static char sccsid[] = "@(#)rwhod.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: rwhod.c,v 1.35 2007/12/15 19:44:56 perry Exp $");
__RCSID("$NetBSD: rwhod.c,v 1.36 2008/07/13 20:07:49 dholland Exp $");
#endif
#endif /* not lint */
@ -373,8 +373,8 @@ send_host_information(int s)
count++;
(void)getutentries(NULL, &ep);
/* XXX probably should expose utmp mtime, check that instead */
if (ep != ohead) {
freeutentries(ep);
wlast = &mywd.wd_we[1024 / sizeof(struct whoent) - 1];
for (; ep; ep = ep->next) {
(void)strncpy(we->we_utmp.out_line, ep->line,

View File

@ -1,4 +1,4 @@
/* $NetBSD: syslogd.c,v 1.84 2006/11/13 20:24:00 christos Exp $ */
/* $NetBSD: syslogd.c,v 1.85 2008/07/13 20:07:49 dholland Exp $ */
/*
* Copyright (c) 1983, 1988, 1993, 1994
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993, 1994\n\
#if 0
static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94";
#else
__RCSID("$NetBSD: syslogd.c,v 1.84 2006/11/13 20:24:00 christos Exp $");
__RCSID("$NetBSD: syslogd.c,v 1.85 2008/07/13 20:07:49 dholland Exp $");
#endif
#endif /* not lint */
@ -1378,17 +1378,12 @@ wallmsg(struct filed *f, struct iovec *iov, size_t iovcnt)
static int reenter; /* avoid calling ourselves */
int i;
char *p;
static struct utmpentry *ohead = NULL;
struct utmpentry *ep;
if (reenter++)
return;
(void)getutentries(NULL, &ep);
if (ep != ohead) {
freeutentries(ohead);
ohead = ep;
}
/* NOSTRICT */
for (; ep; ep = ep->next) {
if (f->f_type == F_WALL) {