mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 22:20:26 +00:00
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:
parent
857fb75bf7
commit
f5e0f0c60a
@ -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] );
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -274,6 +274,7 @@ void select_loop(void)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!active_users) break; /* last user removed by a timeout */
|
||||
}
|
||||
|
||||
sigprocmask( SIG_UNBLOCK, &sigset, NULL );
|
||||
|
Loading…
Reference in New Issue
Block a user