From f5e0f0c60a7d9b2e01ae18da5c9989c06b550187 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 3 Apr 2002 22:51:18 +0000 Subject: [PATCH] Added timer on server exit to wait a bit for new clients. Don't remove the socket until the registry is closed to avoid a race. --- server/main.c | 7 ++++--- server/object.h | 2 +- server/process.c | 2 +- server/request.c | 37 +++++++++++++++++++++++++++---------- server/select.c | 1 + 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/server/main.c b/server/main.c index c6ecfd3499..852c93cb3a 100644 --- a/server/main.c +++ b/server/main.c @@ -33,7 +33,7 @@ /* command-line options */ int debug_level = 0; -int persistent_server = 0; +int master_socket_timeout = 3; /* master socket timeout in seconds, default is 3 s */ /* parse-line args */ /* FIXME: should probably use getopt, and add a (more complete?) help option */ @@ -43,7 +43,7 @@ static void usage(const char *exeName) fprintf(stderr, "\nusage: %s [options]\n\n", exeName); fprintf(stderr, "options:\n"); fprintf(stderr, " -d set debug level to \n"); - fprintf(stderr, " -p make server persistent\n"); + fprintf(stderr, " -p[n] make server persistent, optionally for n seconds\n"); fprintf(stderr, " -h display this help message\n"); fprintf(stderr, "\n"); } @@ -66,7 +66,8 @@ static void parse_args( int argc, char *argv[] ) exit(0); break; case 'p': - persistent_server = 1; + if (isdigit(argv[i][2])) master_socket_timeout = atoi( argv[i] + 2 ); + else master_socket_timeout = -1; break; default: fprintf( stderr, "Unknown option '%s'\n", argv[i] ); diff --git a/server/object.h b/server/object.h index 378a1aec88..6ccbeafe5f 100644 --- a/server/object.h +++ b/server/object.h @@ -198,7 +198,7 @@ extern void release_global_atom( atom_t atom ); /* command-line options */ extern int debug_level; -extern int persistent_server; +extern int master_socket_timeout; /* server start time used for GetTickCount() */ extern unsigned int server_start_ticks; diff --git a/server/process.c b/server/process.c index 8de97b0a98..2162be2f01 100644 --- a/server/process.c +++ b/server/process.c @@ -497,7 +497,7 @@ static void process_killed( struct process *process ) /* last process died, close global handles */ close_global_handles(); /* this will cause the select loop to terminate */ - if (!persistent_server) close_master_socket(); + close_master_socket(); } } diff --git a/server/request.c b/server/request.c index 623520d1d8..7ed598fcd6 100644 --- a/server/request.c +++ b/server/request.c @@ -60,12 +60,12 @@ struct master_socket { - struct object obj; /* object header */ + struct object obj; /* object header */ + struct timeout_user *timeout; /* timeout on last process exit */ }; static void master_socket_dump( struct object *obj, int verbose ); static void master_socket_poll_event( struct object *obj, int event ); -static void master_socket_destroy( struct object *obj ); static const struct object_ops master_socket_ops = { @@ -81,7 +81,7 @@ static const struct object_ops master_socket_ops = no_flush, /* flush */ no_get_file_info, /* get_file_info */ NULL, /* queue_async */ - master_socket_destroy /* destroy */ + no_destroy /* destroy */ }; @@ -447,6 +447,11 @@ static void master_socket_poll_event( struct object *obj, int event ) int len = sizeof(dummy); int client = accept( master_socket->obj.fd, (struct sockaddr *) &dummy, &len ); if (client == -1) return; + if (sock->timeout) + { + remove_timeout_user( sock->timeout ); + sock->timeout = NULL; + } fcntl( client, F_SETFL, O_NONBLOCK ); create_process( client ); } @@ -459,11 +464,6 @@ static void socket_cleanup(void) if (!do_it_once++) unlink( SOCKETNAME ); } -static void master_socket_destroy( struct object *obj ) -{ - socket_cleanup(); -} - /* return the configuration directory ($WINEPREFIX or $HOME/.wine) */ const char *get_config_dir(void) { @@ -557,6 +557,7 @@ void open_master_socket(void) if (!(master_socket = alloc_object( &master_socket_ops, fd ))) fatal_error( "out of memory\n" ); + master_socket->timeout = NULL; set_select_events( &master_socket->obj, POLLIN ); /* setup msghdr structure constant fields */ @@ -581,14 +582,30 @@ void open_master_socket(void) } } -/* close the master socket and stop waiting for new clients */ -void close_master_socket(void) +/* master socket timer expiration handler */ +static void close_socket_timeout( void *arg ) { /* if a new client is waiting, we keep on running */ if (!check_select_events( master_socket->obj.fd, POLLIN )) release_object( master_socket ); } +/* close the master socket and stop waiting for new clients */ +void close_master_socket(void) +{ + struct timeval when; + + if (master_socket_timeout == -1) return; /* just keep running forever */ + + if (master_socket_timeout) + { + gettimeofday( &when, 0 ); + add_timeout( &when, master_socket_timeout * 1000 ); + master_socket->timeout = add_timeout_user( &when, close_socket_timeout, NULL ); + } + else close_socket_timeout( NULL ); /* close it right away */ +} + /* lock/unlock the master socket to stop accepting new clients */ void lock_master_socket( int locked ) { diff --git a/server/select.c b/server/select.c index 065c456f48..24cbdb68fe 100644 --- a/server/select.c +++ b/server/select.c @@ -274,6 +274,7 @@ void select_loop(void) break; } } + if (!active_users) break; /* last user removed by a timeout */ } sigprocmask( SIG_UNBLOCK, &sigset, NULL ); -- 2.32.0.93.g670b81a890