server: New scheme for cleaning up objects on server exit.

Objects stored in static variables can now be marked when they are
created and are automatically cleaned up on exit. This avoids having
to export a bunch of close_* functions.
This commit is contained in:
Alexandre Julliard 2006-03-22 20:32:04 +01:00
parent b877d84af0
commit b00fb174f6
10 changed files with 64 additions and 88 deletions

View File

@ -294,11 +294,6 @@ void *open_object_dir( struct directory *root, const struct unicode_str *name,
/* Global initialization */
static struct directory *dir_driver, *dir_device;
static struct symlink *link_dosdev, *link_global1, *link_global2, *link_local;
static struct named_pipe_device *dev_named_pipe;
static struct mailslot_device *dev_mailslot;
void init_directories(void)
{
/* Directories */
@ -325,11 +320,15 @@ void init_directories(void)
static const struct unicode_str pipe_str = {pipeW, sizeof(pipeW)};
static const struct unicode_str mailslot_str = {mailslotW, sizeof(mailslotW)};
struct directory *dir_global, *dir_basenamed;
struct directory *dir_driver, *dir_device, *dir_global, *dir_basenamed;
struct symlink *link_dosdev, *link_global1, *link_global2, *link_local;
root_directory = create_directory( NULL, NULL, 0, HASH_SIZE );
dir_driver = create_directory( root_directory, &dir_driver_str, 0, HASH_SIZE );
dir_device = create_directory( root_directory, &dir_device_str, 0, HASH_SIZE );
make_object_static( &root_directory->obj );
make_object_static( &dir_driver->obj );
make_object_static( &dir_device->obj );
dir_global = create_directory( NULL, &dir_global_str, 0, HASH_SIZE );
/* use a larger hash table for this one since it can contain a lot of objects */
@ -340,32 +339,20 @@ void init_directories(void)
link_global1 = create_symlink( dir_global, &link_global_str, 0, &dir_global_str );
link_global2 = create_symlink( dir_basenamed, &link_global_str, 0, &dir_basenamed_str );
link_local = create_symlink( dir_basenamed, &link_local_str, 0, &dir_basenamed_str );
make_object_static( (struct object *)link_dosdev );
make_object_static( (struct object *)link_global1 );
make_object_static( (struct object *)link_global2 );
make_object_static( (struct object *)link_local );
/* devices */
dev_named_pipe = create_named_pipe_device( dir_global, &pipe_str );
dev_mailslot = create_mailslot_device( dir_global, &mailslot_str );
create_named_pipe_device( dir_global, &pipe_str );
create_mailslot_device( dir_global, &mailslot_str );
/* the symlinks or devices hold references so we can release these */
release_object( dir_global );
release_object( dir_basenamed );
}
void close_directories(void)
{
release_object( dev_named_pipe );
release_object( dev_mailslot );
release_object( link_dosdev );
release_object( link_global1 );
release_object( link_global2 );
release_object( link_local );
release_object( dir_device );
release_object( dir_driver );
release_object( root_directory );
}
/* create a directory object */
DECL_HANDLER(create_directory)
{

View File

@ -247,6 +247,7 @@ static obj_handle_t alloc_global_handle( void *obj, unsigned int access )
{
if (!(global_table = (struct handle_table *)alloc_handle_table( NULL, 0 )))
return 0;
make_object_static( &global_table->obj );
}
return handle_local_to_global( alloc_entry( global_table, obj, access ));
}
@ -359,16 +360,6 @@ int close_handle( struct process *process, obj_handle_t handle, int *fd )
return 1;
}
/* close all the global handles */
void close_global_handles(void)
{
if (global_table)
{
release_object( global_table );
global_table = NULL;
}
}
/* retrieve the object corresponding to one of the magic pseudo-handles */
static inline struct object *get_magic_handle( obj_handle_t handle )
{

View File

@ -52,6 +52,4 @@ extern struct handle_table *copy_handle_table( struct process *process, struct p
extern unsigned int get_handle_table_count( struct process *process);
extern int flush_cached_fd( struct process *process, obj_handle_t handle );
extern void close_global_handles(void);
#endif /* __WINE_SERVER_HANDLE_H */

View File

@ -310,7 +310,7 @@ static int mailslot_device_get_file_info( struct fd *fd )
return 0;
}
struct mailslot_device *create_mailslot_device( struct directory *root, const struct unicode_str *name )
void create_mailslot_device( struct directory *root, const struct unicode_str *name )
{
struct mailslot_device *dev;
@ -325,7 +325,7 @@ struct mailslot_device *create_mailslot_device( struct directory *root, const st
dev = NULL;
}
}
return dev;
if (dev) make_object_static( &dev->obj );
}
static struct mailslot *create_mailslot( struct directory *root,

View File

@ -443,8 +443,7 @@ static int named_pipe_device_get_file_info( struct fd *fd )
return 0;
}
struct named_pipe_device *create_named_pipe_device( struct directory *root,
const struct unicode_str *name )
void create_named_pipe_device( struct directory *root, const struct unicode_str *name )
{
struct named_pipe_device *dev;
@ -459,7 +458,7 @@ struct named_pipe_device *create_named_pipe_device( struct directory *root,
dev = NULL;
}
}
return dev;
if (dev) make_object_static( &dev->obj );
}
static int pipe_data_remaining( struct pipe_server *server )

View File

@ -56,11 +56,18 @@ struct namespace
#ifdef DEBUG_OBJECTS
static struct list object_list = LIST_INIT(object_list);
static struct list static_object_list = LIST_INIT(static_object_list);
void dump_objects(void)
{
struct list *p;
LIST_FOR_EACH( p, &static_object_list )
{
struct object *ptr = LIST_ENTRY( p, struct object, obj_list );
fprintf( stderr, "%p:%d: ", ptr, ptr->refcount );
ptr->ops->dump( ptr, 1 );
}
LIST_FOR_EACH( p, &object_list )
{
struct object *ptr = LIST_ENTRY( p, struct object, obj_list );
@ -68,7 +75,25 @@ void dump_objects(void)
ptr->ops->dump( ptr, 1 );
}
}
#endif
void close_objects(void)
{
struct list *ptr;
/* release the static objects */
while ((ptr = list_head( &static_object_list )))
{
struct object *obj = LIST_ENTRY( ptr, struct object, obj_list );
/* move it back to the standard list before freeing */
list_remove( &obj->obj_list );
list_add_head( &object_list, &obj->obj_list );
release_object( obj );
}
dump_objects(); /* dump any remaining objects */
}
#endif /* DEBUG_OBJECTS */
/*****************************************************************/
@ -224,6 +249,15 @@ void unlink_named_object( struct object *obj )
obj->name = NULL;
}
/* mark an object as being stored statically, i.e. only released at shutdown */
void make_object_static( struct object *obj )
{
#ifdef DEBUG_OBJECTS
list_remove( &obj->obj_list );
list_add_head( &static_object_list, &obj->obj_list );
#endif
}
/* grab an object (i.e. increment its refcount) and return the object */
struct object *grab_object( void *ptr )
{

View File

@ -110,6 +110,7 @@ extern void *create_object( struct namespace *namespace, const struct object_ops
extern void *create_named_object( struct namespace *namespace, const struct object_ops *ops,
const struct unicode_str *name, unsigned int attributes );
extern void unlink_named_object( struct object *obj );
extern void make_object_static( struct object *obj );
extern struct namespace *create_namespace( unsigned int hash_size );
/* grab/release_object can take any pointer, but you better make sure */
/* that the thing pointed to starts with a struct object... */
@ -127,6 +128,7 @@ extern int no_close_handle( struct object *obj, struct process *process, obj_han
extern void no_destroy( struct object *obj );
#ifdef DEBUG_OBJECTS
extern void dump_objects(void);
extern void close_objects(void);
#endif
/* event functions */
@ -167,7 +169,6 @@ extern int get_page_size(void);
extern void init_registry(void);
extern void flush_registry(void);
extern void close_registry(void);
/* signal functions */
@ -175,7 +176,6 @@ extern void start_watchdog(void);
extern void stop_watchdog(void);
extern int watchdog_triggered(void);
extern void init_signals(void);
extern void close_signals(void);
/* atom functions */
@ -194,7 +194,6 @@ extern void *create_named_object_dir( struct directory *root, const struct unico
extern void *open_object_dir( struct directory *root, const struct unicode_str *name,
unsigned int attr, const struct object_ops *ops );
extern void init_directories(void);
extern void close_directories(void);
/* symbolic link functions */
@ -202,10 +201,8 @@ extern struct symlink *create_symlink( struct directory *root, const struct unic
unsigned int attr, const struct unicode_str *target );
/* devices */
extern struct named_pipe_device *create_named_pipe_device( struct directory *root,
const struct unicode_str *name );
extern struct mailslot_device *create_mailslot_device( struct directory *root,
const struct unicode_str *name );
extern void create_named_pipe_device( struct directory *root, const struct unicode_str *name );
extern void create_mailslot_device( struct directory *root, const struct unicode_str *name );
/* global variables */

View File

@ -1442,7 +1442,10 @@ static void load_init_registry_from_file( const char *filename, struct key *key
assert( save_branch_count < MAX_SAVE_BRANCH_INFO );
if ((save_branch_info[save_branch_count].path = strdup( filename )))
{
save_branch_info[save_branch_count++].key = (struct key *)grab_object( key );
make_object_static( &key->obj );
}
}
static WCHAR *format_user_registry_path( const SID *sid, struct unicode_str *path )
@ -1488,6 +1491,7 @@ void init_registry(void)
/* create the root key */
root_key = alloc_key( &root_name, time(NULL) );
assert( root_key );
make_object_static( &root_key->obj );
if (!(filename = malloc( strlen(config) + 16 ))) fatal_error( "out of memory\n" );
strcpy( filename, config );
@ -1694,21 +1698,6 @@ void flush_registry(void)
}
}
/* close the top-level keys; used on server exit */
void close_registry(void)
{
int i;
if (save_timeout_user) remove_timeout_user( save_timeout_user );
save_timeout_user = NULL;
for (i = 0; i < save_branch_count; i++)
{
release_object( save_branch_info[i].key );
free( save_branch_info[i].path );
}
release_object( root_key );
}
/* create a registry key */
DECL_HANDLER(create_key)

View File

@ -58,10 +58,7 @@
#include "wine/library.h"
#include "file.h"
#include "handle.h"
#include "thread.h"
#include "process.h"
#include "user.h"
#define WANT_REQUEST_HANDLERS
#include "request.h"
@ -715,6 +712,7 @@ static void acquire_lock(void)
fatal_error( "out of memory\n" );
master_socket->timeout = NULL;
set_fd_events( master_socket->fd, POLLIN );
make_object_static( &master_socket->obj );
}
/* open the master server socket and start waiting for new clients */
@ -798,16 +796,9 @@ static void close_socket_timeout( void *arg )
if (debug_level) fprintf( stderr, "wineserver: exiting (pid=%ld)\n", (long) getpid() );
#ifdef DEBUG_OBJECTS
/* shut down everything properly */
release_object( master_socket );
close_signals();
close_global_handles();
close_registry();
close_directories();
dump_objects(); /* dump any remaining objects */
#else
exit(0);
close_objects(); /* shut down everything properly */
#endif
exit(0);
}
/* close the master socket and stop waiting for new clients */

View File

@ -91,8 +91,6 @@ static struct handler *handler_sigint;
static struct handler *handler_sigchld;
static struct handler *handler_sigio;
static sigset_t blocked_sigset;
static int watchdog;
/* create a signal handler */
@ -118,6 +116,7 @@ static struct handler *create_handler( signal_callback callback )
return NULL;
}
set_fd_events( handler->fd, POLLIN );
make_object_static( &handler->obj );
return handler;
}
@ -265,6 +264,7 @@ static int core_dump_disabled( void )
void init_signals(void)
{
struct sigaction action;
sigset_t blocked_sigset;
if (!(handler_sighup = create_handler( sighup_callback ))) goto error;
if (!(handler_sigterm = create_handler( sigterm_callback ))) goto error;
@ -318,13 +318,3 @@ error:
fprintf( stderr, "failed to initialize signal handlers\n" );
exit(1);
}
void close_signals(void)
{
sigprocmask( SIG_BLOCK, &blocked_sigset, NULL );
release_object( handler_sighup );
release_object( handler_sigterm );
release_object( handler_sigint );
release_object( handler_sigchld );
release_object( handler_sigio );
}