Added -k option to kill an existing wineserver.

This commit is contained in:
Alexandre Julliard 2002-08-16 20:02:15 +00:00
parent bbea20d675
commit 40043ed26f
6 changed files with 103 additions and 21 deletions

View File

@ -46,13 +46,14 @@ static void usage(void)
fprintf(stderr, " -d<n> set debug level to <n>\n");
fprintf(stderr, " -p[n] make server persistent, optionally for n seconds\n");
fprintf(stderr, " -w wait until the current wineserver terminates\n");
fprintf(stderr, " -k[n] kill the current wineserver, optionally with signal n\n");
fprintf(stderr, " -h display this help message\n");
fprintf(stderr, "\n");
}
static void parse_args( int argc, char *argv[] )
{
int i;
int i, ret;
server_argv0 = argv[0];
for (i = 1; i < argc; i++)
@ -76,6 +77,10 @@ static void parse_args( int argc, char *argv[] )
case 'w':
wait_for_lock();
exit(0);
case 'k':
if (isdigit(argv[i][2])) ret = kill_lock_owner( atoi(argv[i] + 2) );
else ret = kill_lock_owner(-1);
exit( !ret );
default:
fprintf( stderr, "wineserver: unknown option '%s'\n", argv[i] );
usage();

View File

@ -466,6 +466,20 @@ static void process_unload_dll( struct process *process, void *base )
set_error( STATUS_INVALID_PARAMETER );
}
/* kill all processes */
void kill_all_processes( struct process *skip, int exit_code )
{
for (;;)
{
struct process *process = first_process;
while (process && (!process->running_threads || process == skip))
process = process->next;
if (!process) break;
kill_process( process, NULL, exit_code );
}
}
/* kill all processes being attached to a console renderer */
void kill_console_processes( struct thread *renderer, int exit_code )
{

View File

@ -105,6 +105,7 @@ extern void remove_process_thread( struct process *process,
struct thread *thread );
extern void suspend_process( struct process *process );
extern void resume_process( struct process *process );
extern void kill_all_processes( struct process *skip, int exit_code );
extern void kill_process( struct process *process, struct thread *skip, int exit_code );
extern void kill_console_processes( struct thread *renderer, int exit_code );
extern void kill_debugged_processes( struct thread *debugger, int exit_code );

View File

@ -513,6 +513,28 @@ static void create_server_dir(void)
free( server_dir );
}
/* create the lock file and return its file descriptor */
static int create_server_lock(void)
{
struct stat st;
int fd;
if (lstat( server_lock_name, &st ) == -1)
{
if (errno != ENOENT)
fatal_perror( "lstat %s/%s", wine_get_server_dir(), server_lock_name );
}
else
{
if (!S_ISREG(st.st_mode))
fatal_error( "%s/%s is not a regular file\n", wine_get_server_dir(), server_lock_name );
}
if ((fd = open( server_lock_name, O_CREAT|O_TRUNC|O_WRONLY, 0600 )) == -1)
fatal_perror( "error creating %s/%s", wine_get_server_dir(), server_lock_name );
return fd;
}
/* wait for the server lock */
int wait_for_lock(void)
{
@ -520,8 +542,7 @@ int wait_for_lock(void)
struct flock fl;
create_server_dir();
if ((fd = open( server_lock_name, O_TRUNC|O_WRONLY, 0600 )) == -1)
return -1;
fd = create_server_lock();
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
@ -533,28 +554,59 @@ int wait_for_lock(void)
return r;
}
/* kill the wine server holding the lock */
int kill_lock_owner( int sig )
{
int fd, i, ret = 0;
pid_t pid = 0;
struct flock fl;
create_server_dir();
fd = create_server_lock();
for (i = 0; i < 10; i++)
{
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
if (fcntl( fd, F_GETLK, &fl ) == -1) goto done;
if (fl.l_type != F_WRLCK) goto done; /* the file is not locked */
if (!pid) /* first time around */
{
if (!(pid = fl.l_pid)) goto done; /* shouldn't happen */
if (sig == -1)
{
if (kill( pid, SIGINT ) == -1) goto done;
kill( pid, SIGCONT );
ret = 1;
}
else /* just send the specified signal and return */
{
ret = (kill( pid, sig ) != -1);
goto done;
}
}
else if (fl.l_pid != pid) goto done; /* no longer the same process */
sleep( 1 );
}
/* waited long enough, now kill it */
kill( pid, SIGKILL );
done:
close( fd );
return ret;
}
/* acquire the main server lock */
static void acquire_lock(void)
{
const char *server_dir_name = wine_get_server_dir();
struct sockaddr_un addr;
struct stat st;
struct flock fl;
int fd, slen, got_lock = 0;
if (lstat( server_lock_name, &st ) == -1)
{
if (errno != ENOENT)
fatal_perror( "lstat %s/%s", server_dir_name, server_lock_name );
}
else
{
if (!S_ISREG(st.st_mode))
fatal_error( "%s/%s is not a regular file\n", server_dir_name, server_lock_name );
}
if ((fd = open( server_lock_name, O_CREAT|O_TRUNC|O_WRONLY, 0600 )) == -1)
fatal_perror( "error creating %s/%s", server_dir_name, server_lock_name );
fd = create_server_lock();
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
@ -570,7 +622,7 @@ static void acquire_lock(void)
"Warning: a previous instance of the wine server seems to have crashed.\n"
"Please run 'gdb %s %s/core',\n"
"type 'backtrace' at the gdb prompt and report the results. Thanks.\n\n",
server_argv0, server_dir_name );
server_argv0, wine_get_server_dir() );
}
unlink( server_socket_name ); /* we got the lock, we can safely remove the socket */
got_lock = 1;
@ -590,7 +642,7 @@ static void acquire_lock(void)
case EAGAIN:
exit(2); /* we didn't get the lock, exit with special status */
default:
fatal_perror( "fcntl %s/%s", server_dir_name, server_lock_name );
fatal_perror( "fcntl %s/%s", wine_get_server_dir(), server_lock_name );
}
/* it seems we can't use locks on this fs, so we will use the socket existence as lock */
close( fd );

View File

@ -60,6 +60,7 @@ extern void open_master_socket(void);
extern void close_master_socket(void);
extern void lock_master_socket( int locked );
extern int wait_for_lock(void);
extern int kill_lock_owner( int sig );
extern void trace_request(void);
extern void trace_reply( enum request req, const union generic_reply *reply );

View File

@ -31,7 +31,7 @@
#include "object.h"
#include "thread.h"
#include "process.h"
struct timeout_user
{
@ -229,6 +229,14 @@ static void sigterm_handler()
exit(1);
}
/* SIGINT handler */
static void sigint_handler()
{
kill_all_processes( NULL, 1 );
flush_registry();
exit(1);
}
/* server main loop */
void select_loop(void)
{
@ -252,8 +260,9 @@ void select_loop(void)
sigaction( SIGCHLD, &action, NULL );
action.sa_handler = sighup_handler;
sigaction( SIGHUP, &action, NULL );
action.sa_handler = sigterm_handler;
action.sa_handler = sigint_handler;
sigaction( SIGINT, &action, NULL );
action.sa_handler = sigterm_handler;
sigaction( SIGQUIT, &action, NULL );
sigaction( SIGTERM, &action, NULL );