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.
This commit is contained in:
Alexandre Julliard 2002-04-03 22:51:18 +00:00
parent 857fb75bf7
commit f5e0f0c60a
5 changed files with 34 additions and 15 deletions

View File

@ -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<n> set debug level to <n>\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] );

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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 )
{

View File

@ -274,6 +274,7 @@ void select_loop(void)
break;
}
}
if (!active_users) break; /* last user removed by a timeout */
}
sigprocmask( SIG_UNBLOCK, &sigset, NULL );