From 02a53c176e038ab8ef529b66b2cb966fb8458aa9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 25 Feb 2003 04:17:22 +0000 Subject: [PATCH] Added send_thread_signal() function and properly handle errors caused by the thread having already died when we send it a signal. Use -1 instead of 0 as invalid Unix pid value. --- server/console.c | 2 +- server/debugger.c | 6 +----- server/process.c | 2 +- server/ptrace.c | 40 +++++++++++++++++++++++++++++----------- server/thread.c | 4 ++-- server/thread.h | 1 + 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/server/console.c b/server/console.c index 330daacd77e..2cd08ff36bb 100644 --- a/server/console.c +++ b/server/console.c @@ -416,7 +416,7 @@ static int propagate_console_signal_cb(struct process *process, void *user) while (thread) { struct thread *next = thread->proc_next; - kill( thread->unix_pid, csi->signal ); + send_thread_signal( thread, csi->signal ); thread = next; } } diff --git a/server/debugger.c b/server/debugger.c index fdd74616e33..0e9b875037c 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -720,11 +720,7 @@ DECL_HANDLER(debug_break) struct thread *thread; for (thread = process->thread_list; thread; thread = thread->proc_next) { - if (thread->unix_pid) - { - kill( thread->unix_pid, SIGTRAP ); - break; - } + if (send_thread_signal( thread, SIGTRAP )) break; } if (!thread) set_error( STATUS_ACCESS_DENIED ); } diff --git a/server/process.c b/server/process.c index be629750ae3..785c4cbb495 100644 --- a/server/process.c +++ b/server/process.c @@ -969,7 +969,7 @@ DECL_HANDLER(get_startup_info) /* initialize a new process */ DECL_HANDLER(init_process) { - if (!current->unix_pid) + if (current->unix_pid == -1) { fatal_protocol_error( current, "init_process: init_thread not called yet\n" ); return; diff --git a/server/ptrace.c b/server/ptrace.c index 2c0c12bf203..b83ab7d4e27 100644 --- a/server/ptrace.c +++ b/server/ptrace.c @@ -93,7 +93,7 @@ static int handle_child_status( struct thread *thread, int pid, int status ) if (thread && (WIFSIGNALED(status) || WIFEXITED(status))) { thread->attached = 0; - thread->unix_pid = 0; + thread->unix_pid = -1; if (debug_level) { if (WIFSIGNALED(status)) @@ -136,6 +136,23 @@ void wait4_thread( struct thread *thread, int signal ) } while (res && res != signal); } +/* send a Unix signal to a specific thread */ +int send_thread_signal( struct thread *thread, int sig ) +{ + int ret = -1; + + if (thread->unix_pid != -1) + { + ret = kill( thread->unix_pid, sig ); + if (ret == -1 && errno == ESRCH) /* thread got killed */ + { + thread->unix_pid = -1; + thread->attached = 0; + } + } + return (ret != -1); +} + /* attach to a Unix thread */ static int attach_thread( struct thread *thread ) { @@ -143,7 +160,7 @@ static int attach_thread( struct thread *thread ) if (!use_ptrace) return 0; if (ptrace( PTRACE_ATTACH, thread->unix_pid, 0, 0 ) == -1) { - if (errno == ESRCH) thread->unix_pid = 0; /* process got killed */ + if (errno == ESRCH) thread->unix_pid = -1; /* thread got killed */ return 0; } if (debug_level) fprintf( stderr, "%04x: *attached*\n", thread->id ); @@ -155,12 +172,13 @@ static int attach_thread( struct thread *thread ) /* detach from a Unix thread and kill it */ void detach_thread( struct thread *thread, int sig ) { - if (!thread->unix_pid) return; + if (thread->unix_pid == -1) return; if (thread->attached) { /* make sure it is stopped */ suspend_thread( thread, 0 ); - if (sig) kill( thread->unix_pid, sig ); + if (sig) send_thread_signal( thread, sig ); + if (thread->unix_pid == -1) return; if (debug_level) fprintf( stderr, "%04x: *detached*\n", thread->id ); ptrace( PTRACE_DETACH, thread->unix_pid, (caddr_t)1, sig ); thread->suspend = 0; /* detach makes it continue */ @@ -168,7 +186,7 @@ void detach_thread( struct thread *thread, int sig ) } else { - if (sig) kill( thread->unix_pid, sig ); + if (sig) send_thread_signal( thread, sig ); if (thread->suspend + thread->process->suspend) continue_thread( thread ); } } @@ -177,21 +195,21 @@ void detach_thread( struct thread *thread, int sig ) void stop_thread( struct thread *thread ) { /* can't stop a thread while initialisation is in progress */ - if (!thread->unix_pid || !is_process_init_done(thread->process)) return; + if (thread->unix_pid == -1 || !is_process_init_done(thread->process)) return; /* first try to attach to it */ if (!thread->attached) if (attach_thread( thread )) return; /* this will have stopped it */ /* attached already, or attach failed -> send a signal */ - if (!thread->unix_pid) return; - kill( thread->unix_pid, SIGSTOP ); + if (thread->unix_pid == -1) return; + send_thread_signal( thread, SIGSTOP ); if (thread->attached) wait4_thread( thread, SIGSTOP ); } /* make a thread continue (at the Unix level) */ void continue_thread( struct thread *thread ) { - if (!thread->unix_pid) return; - if (!thread->attached) kill( thread->unix_pid, SIGCONT ); + if (thread->unix_pid == -1) return; + if (!thread->attached) send_thread_signal( thread, SIGCONT ); else ptrace( get_thread_single_step(thread) ? PTRACE_SINGLESTEP : PTRACE_CONT, thread->unix_pid, (caddr_t)1, SIGSTOP ); } @@ -206,7 +224,7 @@ int suspend_for_ptrace( struct thread *thread ) return 1; } /* can't stop a thread while initialisation is in progress */ - if (!thread->unix_pid || !is_process_init_done(thread->process)) goto error; + if (thread->unix_pid == -1 || !is_process_init_done(thread->process)) goto error; thread->suspend++; if (attach_thread( thread )) return 1; thread->suspend--; diff --git a/server/thread.c b/server/thread.c index 2b53d598c83..1a9244f8323 100644 --- a/server/thread.c +++ b/server/thread.c @@ -108,7 +108,7 @@ inline static void init_thread_structure( struct thread *thread ) { int i; - thread->unix_pid = 0; /* not known yet */ + thread->unix_pid = -1; /* not known yet */ thread->context = NULL; thread->teb = NULL; thread->mutex = NULL; @@ -814,7 +814,7 @@ DECL_HANDLER(init_thread) int reply_fd = thread_get_inflight_fd( current, req->reply_fd ); int wait_fd = thread_get_inflight_fd( current, req->wait_fd ); - if (current->unix_pid) + if (current->unix_pid != -1) { fatal_protocol_error( current, "init_thread: already running\n" ); goto error; diff --git a/server/thread.h b/server/thread.h index 250174f303b..a46f3897602 100644 --- a/server/thread.h +++ b/server/thread.h @@ -135,6 +135,7 @@ extern int read_thread_int( struct thread *thread, const int *addr, int *data ); extern int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask ); extern void *get_thread_ip( struct thread *thread ); extern int get_thread_single_step( struct thread *thread ); +extern int send_thread_signal( struct thread *thread, int sig ); extern unsigned int global_error; /* global error code for when no thread is current */