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:
parent
d7c58f547e
commit
3340f02c2b
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue