adts: DynHashTbl: safely handle calling clear() right before dtor

vfs: remove second call to tree_init (now done by vfs_mount)
vfs_tree: fix memory leak due to not destroying root node. commented and
armor-plated things while at it.

This was SVN commit r3647.
This commit is contained in:
janwas 2006-03-16 07:16:24 +00:00
parent 0a1077bdbd
commit 7564827a8a
5 changed files with 56 additions and 20 deletions

View File

@ -115,8 +115,13 @@ public:
void clear()
{
free(tbl);
tbl = 0;
// note: users might call clear() right before the dtor runs,
// so safely handling calling this twice.
if(tbl)
{
free(tbl);
tbl = 0;
}
num_entries = 0;
// rationale: must not set to 0 because expand_tbl only doubles the size.
// don't keep the previous size because it may have become huge and

View File

@ -782,7 +782,6 @@ void vfs_display()
// splitting this into a separate function.
static void vfs_init_once(void)
{
tree_init();
mount_init();
}
@ -805,5 +804,4 @@ void vfs_shutdown()
{
trace_shutdown();
mount_shutdown();
tree_shutdown();
}

View File

@ -617,7 +617,6 @@ LibError vfs_mount(const char* V_mount_point, const char* P_real_path, int flags
LibError mount_rebuild()
{
tree_clear();
tree_init();
remount_all();
return ERR_OK;
}
@ -677,7 +676,7 @@ void mount_init()
void mount_shutdown()
{
tree_clear();
tree_shutdown();
mount_unmount_all();
}

View File

@ -420,30 +420,39 @@ static LibError lookup(TDir* td, const char* path, uint flags, TNode** pnode)
//
//////////////////////////////////////////////////////////////////////////////
// this is a pointer to node_alloc-ed memory instead of a static TDir for
// 2 reasons:
// - no NLSO shutdown order issues; validity is well defined
// (namely between tree_init and tree_shutdown)
// - bonus: tree_init can use it when checking if called twice.
//
//
static TDir* tree_root;
// rationale: can't do this in tree_shutdown - we'd leak at exit.
// calling from tree_add* is ugly as well, so require manual init.
// establish a root node and prepare node_allocator for use.
//
// rationale: calling this from every tree_add* is ugly, so require
// manual init.
void tree_init()
{
// must not call more than once without intervening tree_shutdown
debug_assert(!tree_root);
node_init();
#include "nommgr.h" // placement new
void* mem = node_alloc();
if(mem)
{
#include "nommgr.h"
tree_root = new(mem) TDir("", "");
#include "mmgr.h"
}
}
void tree_shutdown()
{
node_shutdown();
}
// empty all directories and free their memory.
// however, node_allocator's DynArray still remains initialized and
// the root directory is usable (albeit empty).
// use when remounting.
void tree_clear()
{
tree_root->clearR();
@ -451,6 +460,26 @@ void tree_clear()
}
// shut down entirely; destroys node_allocator. any further use after this
// requires another tree_init.
void tree_shutdown()
{
// tree_shutdown should be preceded by tree_init, so ought to be valid.
debug_assert(tree_root);
// careful! do not call tree_clear because it will un-map all
// node memory, which would cause the dtor below to fail.
tree_root->clearR();
// we've still got to destroy the root node (otherwise its
// hash table will leak).
tree_root->~TDir();
tree_root = 0;
node_shutdown();
}
// write a representation of the VFS tree to stdout.
void tree_display()
{

View File

@ -26,14 +26,19 @@ class TDir;
#include "vfs_mount.h" // Mount
// establish a root node and prepare node_allocator for use.
extern void tree_init();
// shut down entirely; destroys node_allocator. any further use after this
// requires another tree_init.
extern void tree_shutdown();
extern void tree_display();
// empties the tree and frees all resources. this is used when
// rebuilding VFS and on exit.
// empty all directories and free their memory.
// however, node_allocator's DynArray still remains initialized and
// the root directory is usable (albeit empty).
// use when remounting.
extern void tree_clear();
extern time_t tree_most_recent_mtime();