fix two problems with shutdown hook code:

(1) after removing a shutdown hook (in shutdownhook_disestablish()),
    free it.  We created it, we have to free it.  Without this,
    shutdownhook_disestablish() leaks memory.
(2) in doshutdownhooks(), before running each hook, remove it from the
    shutdown hook list.  This makes sure that every hook is tried once
    (because doshutdownhooks() is called from before rebooting, and
    a fault in a shutdown hook will cause doshutdownhooks() to be called
    again), but prevents the hooks from potentially being run infinitely
    (as used to be possible, in the above-mentioned situation).
This commit is contained in:
cgd 1996-11-24 00:42:31 +00:00
parent d7c58f547e
commit 3340f02c2b
1 changed files with 18 additions and 8 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_subr.c,v 1.16 1996/10/13 02:27:52 christos Exp $ */
/* $NetBSD: kern_subr.c,v 1.17 1996/11/24 00:42:31 cgd Exp $ */
/*
* Copyright (c) 1982, 1986, 1991, 1993
@ -176,8 +176,6 @@ struct shutdownhook_desc {
LIST_HEAD(, shutdownhook_desc) shutdownhook_list;
int shutdownhooks_done;
void *
shutdownhook_establish(fn, arg)
void (*fn) __P((void *));
@ -213,22 +211,34 @@ shutdownhook_disestablish(vhook)
#endif
LIST_REMOVE((struct shutdownhook_desc *)vhook, sfd_list);
free(vhook, M_DEVBUF);
}
/*
* Run shutdown hooks. Should be invoked immediately before the
* system is halted or rebooted, i.e. after file systems unmounted,
* after crash dump done, etc.
*
* Each shutdown hook is removed from the list before it's run, so that
* it won't be run again.
*/
void
doshutdownhooks()
{
struct shutdownhook_desc *dp;
if (shutdownhooks_done)
return;
for (dp = shutdownhook_list.lh_first; dp != NULL; dp =
dp->sfd_list.le_next)
while ((dp = shutdownhook_list.lh_first) != NULL) {
LIST_REMOVE(dp, sfd_list);
(*dp->sfd_fn)(dp->sfd_arg);
#if 0
/*
* Don't bother freeing the hook structure,, since we may
* be rebooting because of a memory corruption problem,
* and this might only make things worse. It doesn't
* matter, anyway, since the system is just about to
* reboot.
*/
free(dp, M_DEVBUF);
#endif
}
}