From a8497bd037d8c101c8dccb12df2eaf3124f8804f Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sat, 22 Mar 2003 21:00:09 +0000 Subject: [PATCH] Make a distinction between the thread Unix pid and the process wide pid for platforms that use both. --- include/wine/server_protocol.h | 3 ++- scheduler/client.c | 1 + scheduler/sysdeps.c | 2 +- server/context_i386.c | 24 +++++++++++++++++++++++- server/context_powerpc.c | 8 ++++++++ server/context_sparc.c | 8 ++++++++ server/protocol.def | 1 + server/ptrace.c | 18 ++++++++++++++---- server/thread.c | 14 +++++++++----- server/thread.h | 2 ++ server/trace.c | 1 + 11 files changed, 70 insertions(+), 12 deletions(-) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 1364d916a1e..11a59ab22c0 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -301,6 +301,7 @@ struct init_thread_request { struct request_header __header; int unix_pid; + int unix_tid; void* teb; void* entry; int reply_fd; @@ -3556,6 +3557,6 @@ union generic_reply struct get_next_hook_reply get_next_hook_reply; }; -#define SERVER_PROTOCOL_VERSION 101 +#define SERVER_PROTOCOL_VERSION 102 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/scheduler/client.c b/scheduler/client.c index 466fef74100..0304c6fc236 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -695,6 +695,7 @@ void CLIENT_InitThread(void) SERVER_START_REQ( init_thread ) { req->unix_pid = getpid(); + req->unix_tid = -1; req->teb = teb; req->entry = teb->entry_point; req->reply_fd = reply_pipe[1]; diff --git a/scheduler/sysdeps.c b/scheduler/sysdeps.c index a02a0dc29a6..457447f3d11 100644 --- a/scheduler/sysdeps.c +++ b/scheduler/sysdeps.c @@ -178,7 +178,7 @@ int SYSDEPS_SpawnThread( TEB *teb ) { #ifdef HAVE_CLONE if (clone( (int (*)(void *))SYSDEPS_StartThread, teb->stack_top, - CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, teb ) < 0) + CLONE_VM | CLONE_FS | CLONE_FILES, teb ) < 0) return -1; return 0; #elif defined(HAVE_RFORK) diff --git a/server/context_i386.c b/server/context_i386.c index 903f576b1b1..47a5791852d 100644 --- a/server/context_i386.c +++ b/server/context_i386.c @@ -101,7 +101,9 @@ struct kernel_user_regs_struct /* retrieve a debug register */ static inline int get_debug_reg( int pid, int num, DWORD *data ) { - int res = ptrace( PTRACE_PEEKUSER, pid, DR_OFFSET(num), 0 ); + int res; + errno = 0; + res = ptrace( PTRACE_PEEKUSER, pid, DR_OFFSET(num), 0 ); if ((res == -1) && errno) { file_set_error(); @@ -548,6 +550,26 @@ int get_thread_single_step( struct thread *thread ) return (context.EFlags & 0x100) != 0; } +/* send a signal to a specific thread */ +int tkill( int pid, int sig ) +{ +#ifdef __linux__ + int ret; + __asm__( "pushl %%ebx\n\t" + "movl %2,%%ebx\n\t" + "int $0x80\n\t" + "popl %%ebx\n\t" + : "=a" (ret) + : "0" (238) /*SYS_tkill*/, "r" (pid), "c" (sig) ); + if (ret > 0) return ret; + errno = -ret; + return -1; +#else + errno = ENOSYS; + return -1; +#endif +} + /* retrieve the current context of a thread */ DECL_HANDLER(get_thread_context) { diff --git a/server/context_powerpc.c b/server/context_powerpc.c index 3d86c3d8d01..6b7178bfca1 100644 --- a/server/context_powerpc.c +++ b/server/context_powerpc.c @@ -269,6 +269,14 @@ int get_thread_single_step( struct thread *thread ) return (context.Msr & MSR_SE) != 0; } +/* send a signal to a specific thread */ +int tkill( int pid, int sig ) +{ + /* FIXME: should do something here */ + errno = ENOSYS; + return -1; +} + /* retrieve the current context of a thread */ DECL_HANDLER(get_thread_context) { diff --git a/server/context_sparc.c b/server/context_sparc.c index 173c3f74db2..342881b4821 100644 --- a/server/context_sparc.c +++ b/server/context_sparc.c @@ -175,6 +175,14 @@ int get_thread_single_step( struct thread *thread ) return 0; /* FIXME */ } +/* send a signal to a specific thread */ +int tkill( int pid, int sig ) +{ + /* FIXME: should do something here */ + errno = ENOSYS; + return -1; +} + /* retrieve the current context of a thread */ DECL_HANDLER(get_thread_context) { diff --git a/server/protocol.def b/server/protocol.def index 3c27b389729..6af98bc91ad 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -279,6 +279,7 @@ typedef struct /* Initialize a thread; called from the child after fork()/clone() */ @REQ(init_thread) int unix_pid; /* Unix pid of new thread */ + int unix_tid; /* Unix tid of new thread */ void* teb; /* TEB of new thread (in thread address space) */ void* entry; /* thread entry point (in thread address space) */ int reply_fd; /* fd for reply pipe */ diff --git a/server/ptrace.c b/server/ptrace.c index e2b19fc773d..002bc8f63dc 100644 --- a/server/ptrace.c +++ b/server/ptrace.c @@ -66,6 +66,10 @@ inline static int ptrace(int req, ...) { errno = EPERM; return -1; /*FAIL*/ } #endif /* HAVE_SYS_PTRACE_H */ +#ifndef __WALL +#define __WALL 0 +#endif + static const int use_ptrace = 1; /* set to 0 to disable ptrace */ /* handle a status returned by wait4 */ @@ -90,6 +94,7 @@ static int handle_child_status( struct thread *thread, int pid, int status, int { thread->attached = 0; thread->unix_pid = -1; + thread->unix_tid = -1; if (debug_level) { if (WIFSIGNALED(status)) @@ -110,7 +115,7 @@ void sigchld_handler() for (;;) { - if (!(pid = wait4( -1, &status, WUNTRACED | WNOHANG, NULL ))) break; + if (!(pid = wait4( -1, &status, WUNTRACED | WNOHANG | __WALL, NULL ))) break; if (pid != -1) handle_child_status( get_thread_from_pid(pid), pid, status, -1 ); else break; } @@ -123,11 +128,12 @@ static void wait4_thread( struct thread *thread, int signal ) do { - if ((res = wait4( get_ptrace_pid(thread), &status, WUNTRACED, NULL )) == -1) + if ((res = wait4( get_ptrace_pid(thread), &status, WUNTRACED | __WALL, NULL )) == -1) { if (errno == ECHILD) /* must have died */ { thread->unix_pid = -1; + thread->unix_tid = -1; thread->attached = 0; } else perror( "wait4" ); @@ -140,6 +146,7 @@ static void wait4_thread( struct thread *thread, int signal ) /* return the Unix pid to use in ptrace calls for a given thread */ int get_ptrace_pid( struct thread *thread ) { + if (thread->unix_tid != -1) return thread->unix_tid; return thread->unix_pid; } @@ -150,10 +157,13 @@ int send_thread_signal( struct thread *thread, int sig ) if (thread->unix_pid != -1) { - ret = kill( thread->unix_pid, sig ); + if (thread->unix_tid != -1) ret = tkill( thread->unix_tid, sig ); + else ret = kill( thread->unix_pid, sig ); + if (ret == -1 && errno == ESRCH) /* thread got killed */ { thread->unix_pid = -1; + thread->unix_tid = -1; thread->attached = 0; } } @@ -167,7 +177,7 @@ static int attach_thread( struct thread *thread ) if (!use_ptrace) return 0; if (ptrace( PTRACE_ATTACH, get_ptrace_pid(thread), 0, 0 ) == -1) { - if (errno == ESRCH) thread->unix_pid = -1; /* thread got killed */ + if (errno == ESRCH) thread->unix_pid = thread->unix_tid = -1; /* thread got killed */ return 0; } if (debug_level) fprintf( stderr, "%04x: *attached*\n", thread->id ); diff --git a/server/thread.c b/server/thread.c index 3db8b1e1120..0db0ada80e3 100644 --- a/server/thread.c +++ b/server/thread.c @@ -109,6 +109,7 @@ inline static void init_thread_structure( struct thread *thread ) int i; thread->unix_pid = -1; /* not known yet */ + thread->unix_tid = -1; /* not known yet */ thread->context = NULL; thread->teb = NULL; thread->mutex = NULL; @@ -253,8 +254,8 @@ static void dump_thread( struct object *obj, int verbose ) struct thread *thread = (struct thread *)obj; assert( obj->ops == &thread_ops ); - fprintf( stderr, "Thread id=%04x unix pid=%d teb=%p state=%d\n", - thread->id, thread->unix_pid, thread->teb, thread->state ); + fprintf( stderr, "Thread id=%04x unix pid=%d unix tid=%d teb=%p state=%d\n", + thread->id, thread->unix_pid, thread->unix_tid, thread->teb, thread->state ); } static int thread_signaled( struct object *obj, struct thread *thread ) @@ -283,9 +284,11 @@ struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access /* find a thread from a Unix pid */ struct thread *get_thread_from_pid( int pid ) { - struct thread *t = first_thread; - while (t && (t->unix_pid != pid)) t = t->next; - return t; + struct thread *t; + + for (t = first_thread; t; t = t->next) if (t->unix_tid == pid) return t; + for (t = first_thread; t; t = t->next) if (t->unix_pid == pid) return t; + return NULL; } /* set all information about a thread */ @@ -845,6 +848,7 @@ DECL_HANDLER(init_thread) if (!current->reply_fd || !current->wait_fd) return; current->unix_pid = req->unix_pid; + current->unix_tid = req->unix_tid; current->teb = req->teb; if (current->suspend + current->process->suspend > 0) stop_thread( current ); diff --git a/server/thread.h b/server/thread.h index 8050d81b43b..21fcdcb9091 100644 --- a/server/thread.h +++ b/server/thread.h @@ -86,6 +86,7 @@ struct thread int attached; /* is thread attached with ptrace? */ int exit_code; /* thread exit code */ int unix_pid; /* Unix pid of client */ + int unix_tid; /* Unix tid of client */ CONTEXT *context; /* current context if in an exception handler */ void *teb; /* TEB address (in client address space) */ int priority; /* priority level */ @@ -136,6 +137,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 tkill( int pid, int sig ); extern int send_thread_signal( struct thread *thread, int sig ); extern unsigned int global_error; /* global error code for when no thread is current */ diff --git a/server/trace.c b/server/trace.c index 33a93a1a7b4..3dadcc1d329 100644 --- a/server/trace.c +++ b/server/trace.c @@ -459,6 +459,7 @@ static void dump_init_process_done_reply( const struct init_process_done_reply * static void dump_init_thread_request( const struct init_thread_request *req ) { fprintf( stderr, " unix_pid=%d,", req->unix_pid ); + fprintf( stderr, " unix_tid=%d,", req->unix_tid ); fprintf( stderr, " teb=%p,", req->teb ); fprintf( stderr, " entry=%p,", req->entry ); fprintf( stderr, " reply_fd=%d,", req->reply_fd );