I submitted this patch on June 5th, but it appears that it didn't get put in. ChangeLog: include/thread.h scheduler/sysdeps.c scheduler/thread.c server/ptrace.c - Fixed SuspendThread / ResumeThread for LWP threads - Fixed crash in ExitThread SYSDEPS_ExitThread wasn't checking the return code of VirtualQuery. Since the stack is in high memory on Sparc (kernel memory, according to a comment in VirtualQuery) this caused any program which calls ExitThread to crash. That is fixed now. Also, SuspendThread and ResumeThread were using signals. This DOES NOT work with LWP threads. LWP threads are actually in the same process, so sending SIGSTOP to the PID of one thread stops the ENTIRE process. This patch fixes this bug too. Gregg Mattinson Co-op Developer Sun Microsystems of Canada
Index: include/thread.h =================================================================== RCS file: /opcom/comp/ws/wine/CVSROOT/wine/include/thread.h,v retrieving revision 1.1 diff -u -r1.1 thread.h --- /tmp/T01RayjX Fri Jul 12 10:00:20 2002 +++ thread.h Mon Jun 10 14:59:07 2002 @@ -147,6 +147,8 @@ extern void SYSDEPS_ExitThread( int status ) WINE_NORETURN; extern void SYSDEPS_AbortThread( int status ) WINE_NORETURN; extern void SYSDEPS_SwitchToThreadStack( void (*func)(void) ) WINE_NORETURN; +extern void SYSDEPS_SuspendThread( TEB *teb ); +extern void SYSDEPS_ResumeThread( TEB *teb ); /* signal handling */ extern BOOL SIGNAL_Init(void); Index: scheduler/sysdeps.c =================================================================== RCS file: /opcom/comp/ws/wine/CVSROOT/wine/scheduler/sysdeps.c,v retrieving revision 1.1 diff -u -r1.1 sysdeps.c --- /tmp/T04_aWLX Fri Jul 12 14:43:44 2002 +++ sysdeps.c Fri Jul 12 14:40:18 2002 @@ -167,6 +167,32 @@ /*********************************************************************** + * SYSDEPS_SuspendThread + * + * Suspend a thread. + */ +void SYSDEPS_SuspendThread( TEB *teb ) +{ +#ifdef HAVE__LWP_CREATE + _lwp_suspend(teb->pthread_data); +#endif +} + + +/*********************************************************************** + * SYSDEPS_ResumeThread + * + * Resume a thread. + */ +void SYSDEPS_ResumeThread( TEB *teb ) +{ +#ifdef HAVE__LWP_CREATE + _lwp_continue(teb->pthread_data); +#endif +} + + +/*********************************************************************** * SYSDEPS_SpawnThread * * Start running a new thread. @@ -211,7 +237,7 @@ ucontext_t context; _lwp_makecontext( &context, (void(*)(void *))SYSDEPS_StartThread, teb, NULL, teb->stack_base, (char *)teb->stack_top - (char *)teb->stack_base ); - if ( _lwp_create( &context, 0, NULL ) ) + if ( _lwp_create( &context, 0, &teb->pthread_data ) ) return -1; return 0; #endif @@ -279,9 +305,13 @@ MEMORY_BASIC_INFORMATION meminfo; FreeSelector16( teb->stack_sel ); - VirtualQuery( teb->stack_top, &meminfo, sizeof(meminfo) ); - info.stack_base = meminfo.AllocationBase; - info.stack_size = meminfo.RegionSize + ((char *)teb->stack_top - (char *)meminfo.AllocationBase); + if( VirtualQuery( teb->stack_top, &meminfo, sizeof(meminfo) ) ) { + info.stack_base = meminfo.AllocationBase; + info.stack_size = meminfo.RegionSize + ((char *)teb->stack_top - (char *)meminfo.AllocationBase); + } else { + info.stack_base = 0; + info.stack_size = 0; + } info.status = status; SIGNAL_Reset(); Index: scheduler/thread.c =================================================================== RCS file: /opcom/comp/ws/wine/CVSROOT/wine/scheduler/thread.c,v retrieving revision 1.1 diff -u -r1.1 thread.c --- /tmp/T0y3aWrX Fri Jul 12 10:00:54 2002 +++ thread.c Mon Jun 10 15:11:20 2002 @@ -82,6 +82,32 @@ /*********************************************************************** + * THREAD_HandleToTEB + * + * Convert a thread handle to a TEB, making sure it is valid. + */ +static TEB *THREAD_HandleToTEB( HANDLE hthread ) +{ + TEB *ret = NULL; + + if (!hthread) return NtCurrentTeb(); + + SERVER_START_REQ( get_thread_info ) + { + req->handle = hthread; + req->tid_in = 0; + if (!wine_server_call( req )) ret = reply->teb; + } + SERVER_END_REQ; + + if (!ret) + SetLastError( ERROR_INVALID_PARAMETER ); + + return ret; +} + + +/*********************************************************************** * THREAD_InitTEB * * Initialization of a newly created TEB. @@ -628,6 +654,10 @@ if (!wine_server_call_err( req )) ret = reply->count; } SERVER_END_REQ; + + if (ret == 1) + SYSDEPS_ResumeThread( THREAD_HandleToTEB(hthread) ); + return ret; } @@ -649,6 +679,10 @@ if (!wine_server_call_err( req )) ret = reply->count; } SERVER_END_REQ; + + if (ret == 0) + SYSDEPS_SuspendThread( THREAD_HandleToTEB(hthread) ); + return ret; } Index: server/ptrace.c =================================================================== RCS file: /opcom/comp/ws/wine/CVSROOT/wine/server/ptrace.c,v retrieving revision 1.1 diff -u -r1.1 ptrace.c --- /tmp/T0YpaGsX Fri Jul 12 10:00:55 2002 +++ ptrace.c Mon Jun 10 15:13:20 2002 @@ -168,7 +168,9 @@ } else { +#ifndef HAVE__LWP_CREATE if (sig) kill( thread->unix_pid, sig ); +#endif if (thread->suspend + thread->process->suspend) continue_thread( thread ); } } @@ -178,6 +180,7 @@ { /* can't stop a thread while initialisation is in progress */ if (!thread->unix_pid || !is_process_init_done(thread->process)) return; +#ifndef HAVE__LWP_CREATE /* first try to attach to it */ if (!thread->attached) if (attach_thread( thread )) return; /* this will have stopped it */ @@ -185,15 +188,18 @@ if (!thread->unix_pid) return; kill( thread->unix_pid, SIGSTOP ); if (thread->attached) wait4_thread( thread, SIGSTOP ); +#endif } /* make a thread continue (at the Unix level) */ void continue_thread( struct thread *thread ) { if (!thread->unix_pid) return; +#ifndef HAVE__LWP_CREATE if (!thread->attached) kill( thread->unix_pid, SIGCONT ); else ptrace( get_thread_single_step(thread) ? PTRACE_SINGLESTEP : PTRACE_CONT, thread->unix_pid, (caddr_t)1, SIGSTOP ); +#endif } /* suspend a thread to allow using ptrace on it */