Alexandre Julliard : server: Send a SIGKILL to processes that don' t terminate properly.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Aug 14 14:10:24 CDT 2006


Module: wine
Branch: master
Commit: 68e850e602975b4669e7284f4b32b2d4f33b4a32
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=68e850e602975b4669e7284f4b32b2d4f33b4a32

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Aug 14 20:19:42 2006 +0200

server: Send a SIGKILL to processes that don't terminate properly.

---

 server/process.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 server/process.h |    2 ++
 server/thread.c  |    3 +++
 3 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/server/process.c b/server/process.c
index 3f933fe..733b1c5 100644
--- a/server/process.c
+++ b/server/process.c
@@ -217,6 +217,38 @@ static void set_process_startup_state( s
     }
 }
 
+/* final cleanup once we are sure a process is really dead */
+static void process_died( struct process *process )
+{
+    if (debug_level) fprintf( stderr, "%04x: *process killed*\n", process->id );
+    release_object( process );
+    if (!--running_processes) close_master_socket();
+}
+
+/* callback for process sigkill timeout */
+static void process_sigkill( void *private )
+{
+    struct process *process = private;
+
+    process->sigkill_timeout = NULL;
+    kill( process->unix_pid, SIGKILL );
+    process_died( process );
+}
+
+/* start the sigkill timer for a process upon exit */
+static void start_sigkill_timer( struct process *process )
+{
+    grab_object( process );
+    if (process->unix_pid != -1 && process->msg_fd)
+    {
+        struct timeval when = current_time;
+
+        add_timeout( &when, 1000 );
+        process->sigkill_timeout = add_timeout_user( &when, process_sigkill, process );
+    }
+    else process_died( process );
+}
+
 /* create a new process and its main thread */
 /* if the function fails the fd is closed */
 struct thread *create_process( int fd, struct thread *parent_thread, int inherit_all )
@@ -234,6 +266,8 @@ struct thread *create_process( int fd, s
     process->debugger        = NULL;
     process->handles         = NULL;
     process->msg_fd          = NULL;
+    process->sigkill_timeout = NULL;
+    process->unix_pid        = -1;
     process->exit_code       = STILL_ACTIVE;
     process->running_threads = 0;
     process->priority        = PROCESS_PRIOCLASS_NORMAL;
@@ -322,6 +356,8 @@ static void process_destroy( struct obje
     /* we can't have a thread remaining */
     assert( list_empty( &process->thread_list ));
 
+    assert( !process->sigkill_timeout );  /* timeout should hold a reference to the process */
+
     set_process_startup_state( process, STARTUP_ABORTED );
     if (process->console) release_object( process->console );
     if (process->parent) release_object( process->parent );
@@ -362,7 +398,18 @@ static void process_poll_event( struct f
     struct process *process = get_fd_user( fd );
     assert( process->obj.ops == &process_ops );
 
-    if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 );
+    if (event & (POLLERR | POLLHUP))
+    {
+        release_object( process->msg_fd );
+        process->msg_fd = NULL;
+        if (process->sigkill_timeout)  /* already waiting for it to die */
+        {
+            remove_timeout_user( process->sigkill_timeout );
+            process->sigkill_timeout = NULL;
+            process_died( process );
+        }
+        else kill_process( process, NULL, 0 );
+    }
     else if (event & POLLIN) receive_fd( process );
 }
 
@@ -528,8 +575,8 @@ static void process_killed( struct proce
     destroy_process_classes( process );
     remove_process_locks( process );
     set_process_startup_state( process, STARTUP_ABORTED );
+    start_sigkill_timer( process );
     wake_up( &process->obj, 0 );
-    if (!--running_processes) close_master_socket();
 }
 
 /* add a thread to a process running threads list */
diff --git a/server/process.h b/server/process.h
index 6edb1e6..c447e2f 100644
--- a/server/process.h
+++ b/server/process.h
@@ -57,6 +57,8 @@ struct process
     struct fd           *msg_fd;          /* fd for sendmsg/recvmsg */
     process_id_t         id;              /* id of the process */
     process_id_t         group_id;        /* group id of the process */
+    struct timeout_user *sigkill_timeout; /* timeout for final SIGKILL */
+    int                  unix_pid;        /* Unix pid for final SIGKILL */
     int                  exit_code;       /* process exit code */
     int                  running_threads; /* number of threads running in this process */
     struct timeval       start_time;      /* absolute time at process start */
diff --git a/server/thread.c b/server/thread.c
index 9d9f255..36d1d79 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -872,12 +872,15 @@ DECL_HANDLER(init_thread)
 
     if (!process->peb)  /* first thread, initialize the process too */
     {
+        process->unix_pid = current->unix_pid;
         process->peb      = req->peb;
         process->ldt_copy = req->ldt_copy;
         reply->info_size  = init_process( current );
     }
     else
     {
+        if (process->unix_pid != current->unix_pid)
+            process->unix_pid = -1;  /* can happen with linuxthreads */
         if (current->suspend + process->suspend > 0) stop_thread( current );
         generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
     }




More information about the wine-cvs mailing list