Commit d04ccb8e authored by Alexandre Julliard's avatar Alexandre Julliard

Use SIGUSR1 instead of SIGSTOP to suspend threads.

parent 6168a2ea
...@@ -655,6 +655,36 @@ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext ) ...@@ -655,6 +655,36 @@ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
/*********************************************************************** /***********************************************************************
* init_handler
*
* Handler initialization when the full context is not needed.
*/
static void init_handler( const SIGCONTEXT *sigcontext )
{
/* restore a proper %fs for the fault handler */
if (!IS_SELECTOR_SYSTEM(CS_sig(sigcontext)) ||
!IS_SELECTOR_SYSTEM(SS_sig(sigcontext))) /* 16-bit mode */
{
wine_set_fs( SYSLEVEL_Win16CurrentTeb );
}
#ifdef __HAVE_VM86
else if ((void *)EIP_sig(sigcontext) == vm86_return) /* vm86 mode */
{
/* fetch the saved %fs on the stack */
wine_set_fs( *(unsigned int *)ESP_sig(sigcontext) );
}
#endif /* __HAVE_VM86 */
#ifdef FS_sig
else /* 32-bit mode, get %fs at time of the fault */
{
wine_set_fs( FS_sig(sigcontext) );
}
#endif /* FS_sig */
wine_set_gs( NtCurrentTeb()->gs_sel );
}
/***********************************************************************
* save_fpu * save_fpu
* *
* Set the FPU context from a sigcontext. * Set the FPU context from a sigcontext.
...@@ -1037,6 +1067,7 @@ static HANDLER_DEF(fpe_handler) ...@@ -1037,6 +1067,7 @@ static HANDLER_DEF(fpe_handler)
*/ */
static HANDLER_DEF(int_handler) static HANDLER_DEF(int_handler)
{ {
init_handler( HANDLER_CONTEXT );
if (!dispatch_signal(SIGINT)) if (!dispatch_signal(SIGINT))
{ {
EXCEPTION_RECORD rec; EXCEPTION_RECORD rec;
...@@ -1074,6 +1105,19 @@ static HANDLER_DEF(abrt_handler) ...@@ -1074,6 +1105,19 @@ static HANDLER_DEF(abrt_handler)
} }
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static HANDLER_DEF(usr1_handler)
{
init_handler( HANDLER_CONTEXT );
/* wait with 0 timeout, will only return once the thread is no longer suspended */
WaitForMultipleObjectsEx( 0, NULL, FALSE, 0, FALSE );
}
/*********************************************************************** /***********************************************************************
* set_handler * set_handler
* *
...@@ -1160,6 +1204,7 @@ BOOL SIGNAL_Init(void) ...@@ -1160,6 +1204,7 @@ BOOL SIGNAL_Init(void)
if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
if (set_handler( SIGILL, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; if (set_handler( SIGILL, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error; if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error;
if (set_handler( SIGUSR1, have_sigaltstack, (void (*)())usr1_handler ) == -1) goto error;
#ifdef SIGBUS #ifdef SIGBUS
if (set_handler( SIGBUS, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; if (set_handler( SIGBUS, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
#endif #endif
...@@ -1192,6 +1237,7 @@ void SIGNAL_Reset(void) ...@@ -1192,6 +1237,7 @@ void SIGNAL_Reset(void)
sigaddset( &block_set, SIGALRM ); sigaddset( &block_set, SIGALRM );
sigaddset( &block_set, SIGIO ); sigaddset( &block_set, SIGIO );
sigaddset( &block_set, SIGHUP ); sigaddset( &block_set, SIGHUP );
sigaddset( &block_set, SIGUSR1 );
sigaddset( &block_set, SIGUSR2 ); sigaddset( &block_set, SIGUSR2 );
sigprocmask( SIG_BLOCK, &block_set, NULL ); sigprocmask( SIG_BLOCK, &block_set, NULL );
......
...@@ -381,6 +381,7 @@ static HANDLER_DEF(int_handler) ...@@ -381,6 +381,7 @@ static HANDLER_DEF(int_handler)
} }
} }
/********************************************************************** /**********************************************************************
* abrt_handler * abrt_handler
* *
...@@ -402,6 +403,18 @@ static HANDLER_DEF(abrt_handler) ...@@ -402,6 +403,18 @@ static HANDLER_DEF(abrt_handler)
} }
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static HANDLER_DEF(usr1_handler)
{
/* wait with 0 timeout, will only return once the thread is no longer suspended */
WaitForMultipleObjectsEx( 0, NULL, FALSE, 0, FALSE );
}
/*********************************************************************** /***********************************************************************
* set_handler * set_handler
* *
...@@ -461,6 +474,7 @@ BOOL SIGNAL_Init(void) ...@@ -461,6 +474,7 @@ BOOL SIGNAL_Init(void)
if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
if (set_handler( SIGILL, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; if (set_handler( SIGILL, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error; if (set_handler( SIGABRT, have_sigaltstack, (void (*)())abrt_handler ) == -1) goto error;
if (set_handler( SIGUSR1, have_sigaltstack, (void (*)())usr1_handler ) == -1) goto error;
#ifdef SIGBUS #ifdef SIGBUS
if (set_handler( SIGBUS, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; if (set_handler( SIGBUS, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error;
#endif #endif
...@@ -488,6 +502,7 @@ void SIGNAL_Reset(void) ...@@ -488,6 +502,7 @@ void SIGNAL_Reset(void)
sigaddset( &block_set, SIGALRM ); sigaddset( &block_set, SIGALRM );
sigaddset( &block_set, SIGIO ); sigaddset( &block_set, SIGIO );
sigaddset( &block_set, SIGHUP ); sigaddset( &block_set, SIGHUP );
sigaddset( &block_set, SIGUSR1 );
sigaddset( &block_set, SIGUSR2 ); sigaddset( &block_set, SIGUSR2 );
sigprocmask( SIG_BLOCK, &block_set, NULL ); sigprocmask( SIG_BLOCK, &block_set, NULL );
......
...@@ -367,6 +367,19 @@ static HANDLER_DEF(abrt_handler) ...@@ -367,6 +367,19 @@ static HANDLER_DEF(abrt_handler)
restore_context( &context, HANDLER_CONTEXT ); restore_context( &context, HANDLER_CONTEXT );
} }
/**********************************************************************
* usr1_handler
*
* Handler for SIGUSR1, used to signal a thread that it got suspended.
*/
static HANDLER_DEF(usr1_handler)
{
/* wait with 0 timeout, will only return once the thread is no longer suspended */
WaitForMultipleObjectsEx( 0, NULL, FALSE, 0, FALSE );
}
/*********************************************************************** /***********************************************************************
* set_handler * set_handler
* *
...@@ -422,6 +435,7 @@ BOOL SIGNAL_Init(void) ...@@ -422,6 +435,7 @@ BOOL SIGNAL_Init(void)
if (set_handler( SIGBUS, (void (*)())bus_handler ) == -1) goto error; if (set_handler( SIGBUS, (void (*)())bus_handler ) == -1) goto error;
if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error; if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error;
if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error; if (set_handler( SIGABRT, (void (*)())abrt_handler ) == -1) goto error;
if (set_handler( SIGUSR1, (void (*)())usr1_handler ) == -1) goto error;
return TRUE; return TRUE;
error: error:
...@@ -442,6 +456,7 @@ void SIGNAL_Reset(void) ...@@ -442,6 +456,7 @@ void SIGNAL_Reset(void)
sigaddset( &block_set, SIGALRM ); sigaddset( &block_set, SIGALRM );
sigaddset( &block_set, SIGIO ); sigaddset( &block_set, SIGIO );
sigaddset( &block_set, SIGHUP ); sigaddset( &block_set, SIGHUP );
sigaddset( &block_set, SIGUSR1 );
sigaddset( &block_set, SIGUSR2 ); sigaddset( &block_set, SIGUSR2 );
sigprocmask( SIG_BLOCK, &block_set, NULL ); sigprocmask( SIG_BLOCK, &block_set, NULL );
......
...@@ -3551,6 +3551,6 @@ union generic_reply ...@@ -3551,6 +3551,6 @@ union generic_reply
struct get_next_hook_reply get_next_hook_reply; struct get_next_hook_reply get_next_hook_reply;
}; };
#define SERVER_PROTOCOL_VERSION 98 #define SERVER_PROTOCOL_VERSION 99
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -653,6 +653,8 @@ void CLIENT_InitServer(void) ...@@ -653,6 +653,8 @@ void CLIENT_InitServer(void)
sigaddset( &block_set, SIGIO ); sigaddset( &block_set, SIGIO );
sigaddset( &block_set, SIGINT ); sigaddset( &block_set, SIGINT );
sigaddset( &block_set, SIGHUP ); sigaddset( &block_set, SIGHUP );
sigaddset( &block_set, SIGUSR1 );
sigaddset( &block_set, SIGUSR2 );
/* receive the first thread request fd on the main socket */ /* receive the first thread request fd on the main socket */
NtCurrentTeb()->request_fd = receive_fd( &dummy_handle ); NtCurrentTeb()->request_fd = receive_fd( &dummy_handle );
......
...@@ -508,6 +508,14 @@ static void start_process(void) ...@@ -508,6 +508,14 @@ static void start_process(void)
console_app = (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI); console_app = (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI);
if (console_app) current_process.flags |= PDB32_CONSOLE_PROC; if (console_app) current_process.flags |= PDB32_CONSOLE_PROC;
/* Install signal handlers; this cannot be done before, since we cannot
* send exceptions to the debugger before the create process event that
* is sent by REQ_INIT_PROCESS_DONE.
* We do need the handlers in place by the time the request is over, so
* we set them up here. If we segfault between here and the server call
* something is very wrong... */
if (!SIGNAL_Init()) goto error;
/* Signal the parent process to continue */ /* Signal the parent process to continue */
SERVER_START_REQ( init_process_done ) SERVER_START_REQ( init_process_done )
{ {
...@@ -524,11 +532,6 @@ static void start_process(void) ...@@ -524,11 +532,6 @@ static void start_process(void)
} }
SERVER_END_REQ; SERVER_END_REQ;
/* Install signal handlers; this cannot be done before, since we cannot
* send exceptions to the debugger before the create process event that
* is sent by REQ_INIT_PROCESS_DONE */
if (!SIGNAL_Init()) goto error;
/* create the main modref and load dependencies */ /* create the main modref and load dependencies */
if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE ))) if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE )))
goto error; goto error;
......
...@@ -534,7 +534,7 @@ void *get_thread_ip( struct thread *thread ) ...@@ -534,7 +534,7 @@ void *get_thread_ip( struct thread *thread )
if (suspend_for_ptrace( thread )) if (suspend_for_ptrace( thread ))
{ {
get_thread_context( thread, CONTEXT_CONTROL, &context ); get_thread_context( thread, CONTEXT_CONTROL, &context );
resume_thread( thread ); resume_after_ptrace( thread );
} }
return (void *)context.Eip; return (void *)context.Eip;
} }
...@@ -576,7 +576,7 @@ DECL_HANDLER(get_thread_context) ...@@ -576,7 +576,7 @@ DECL_HANDLER(get_thread_context)
if (flags && suspend_for_ptrace( thread )) if (flags && suspend_for_ptrace( thread ))
{ {
get_thread_context( thread, flags, data ); get_thread_context( thread, flags, data );
resume_thread( thread ); resume_after_ptrace( thread );
} }
} }
release_object( thread ); release_object( thread );
...@@ -604,7 +604,7 @@ DECL_HANDLER(set_thread_context) ...@@ -604,7 +604,7 @@ DECL_HANDLER(set_thread_context)
if (flags && suspend_for_ptrace( thread )) if (flags && suspend_for_ptrace( thread ))
{ {
set_thread_context( thread, flags, get_req_data() ); set_thread_context( thread, flags, get_req_data() );
resume_thread( thread ); resume_after_ptrace( thread );
} }
release_object( thread ); release_object( thread );
} }
......
...@@ -252,7 +252,7 @@ void *get_thread_ip( struct thread *thread ) ...@@ -252,7 +252,7 @@ void *get_thread_ip( struct thread *thread )
if (suspend_for_ptrace( thread )) if (suspend_for_ptrace( thread ))
{ {
get_thread_context( thread, CONTEXT_CONTROL, &context ); get_thread_context( thread, CONTEXT_CONTROL, &context );
resume_thread( thread ); resume_after_ptrace( thread );
} }
return (void *)context.Iar; return (void *)context.Iar;
} }
...@@ -293,7 +293,7 @@ DECL_HANDLER(get_thread_context) ...@@ -293,7 +293,7 @@ DECL_HANDLER(get_thread_context)
if (flags && suspend_for_ptrace( thread )) if (flags && suspend_for_ptrace( thread ))
{ {
get_thread_context( thread, flags, data ); get_thread_context( thread, flags, data );
resume_thread( thread ); resume_after_ptrace( thread );
} }
} }
release_object( thread ); release_object( thread );
...@@ -321,7 +321,7 @@ DECL_HANDLER(set_thread_context) ...@@ -321,7 +321,7 @@ DECL_HANDLER(set_thread_context)
if (flags && suspend_for_ptrace( thread )) if (flags && suspend_for_ptrace( thread ))
{ {
set_thread_context( thread, flags, get_req_data() ); set_thread_context( thread, flags, get_req_data() );
resume_thread( thread ); resume_after_ptrace( thread );
} }
release_object( thread ); release_object( thread );
} }
......
...@@ -164,7 +164,7 @@ void *get_thread_ip( struct thread *thread ) ...@@ -164,7 +164,7 @@ void *get_thread_ip( struct thread *thread )
if (suspend_for_ptrace( thread )) if (suspend_for_ptrace( thread ))
{ {
get_thread_context( thread, CONTEXT_CONTROL, &context ); get_thread_context( thread, CONTEXT_CONTROL, &context );
resume_thread( thread ); resume_after_ptrace( thread );
} }
return (void *)context.pc; return (void *)context.pc;
} }
...@@ -199,7 +199,7 @@ DECL_HANDLER(get_thread_context) ...@@ -199,7 +199,7 @@ DECL_HANDLER(get_thread_context)
if (flags && suspend_for_ptrace( thread )) if (flags && suspend_for_ptrace( thread ))
{ {
get_thread_context( thread, flags, data ); get_thread_context( thread, flags, data );
resume_thread( thread ); resume_after_ptrace( thread );
} }
} }
release_object( thread ); release_object( thread );
...@@ -227,7 +227,7 @@ DECL_HANDLER(set_thread_context) ...@@ -227,7 +227,7 @@ DECL_HANDLER(set_thread_context)
if (flags && suspend_for_ptrace( thread )) if (flags && suspend_for_ptrace( thread ))
{ {
set_thread_context( thread, flags, get_req_data() ); set_thread_context( thread, flags, get_req_data() );
resume_thread( thread ); resume_after_ptrace( thread );
} }
release_object( thread ); release_object( thread );
} }
......
...@@ -673,11 +673,7 @@ void resume_process( struct process *process ) ...@@ -673,11 +673,7 @@ void resume_process( struct process *process )
while (thread) while (thread)
{ {
struct thread *next = thread->proc_next; struct thread *next = thread->proc_next;
if (!thread->suspend) if (!thread->suspend) wake_thread( thread );
{
continue_thread( thread );
wake_thread( thread );
}
thread = next; thread = next;
} }
} }
...@@ -781,7 +777,7 @@ static int read_process_memory( struct process *process, const int *addr, size_t ...@@ -781,7 +777,7 @@ static int read_process_memory( struct process *process, const int *addr, size_t
if (read_thread_int( thread, addr++, dest++ ) == -1) break; if (read_thread_int( thread, addr++, dest++ ) == -1) break;
len--; len--;
} }
resume_thread( thread ); resume_after_ptrace( thread );
} }
return !len; return !len;
} }
...@@ -842,7 +838,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len ...@@ -842,7 +838,7 @@ static void write_process_memory( struct process *process, int *addr, size_t len
if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done; if (write_thread_int( thread, addr, *src, last_mask ) == -1) goto done;
done: done:
resume_thread( thread ); resume_after_ptrace( thread );
} }
} }
......
...@@ -69,24 +69,20 @@ inline static int ptrace(int req, ...) { errno = EPERM; return -1; /*FAIL*/ } ...@@ -69,24 +69,20 @@ inline static int ptrace(int req, ...) { errno = EPERM; return -1; /*FAIL*/ }
static const int use_ptrace = 1; /* set to 0 to disable ptrace */ static const int use_ptrace = 1; /* set to 0 to disable ptrace */
/* handle a status returned by wait4 */ /* handle a status returned by wait4 */
static int handle_child_status( struct thread *thread, int pid, int status ) static int handle_child_status( struct thread *thread, int pid, int status, int want_sig )
{ {
if (WIFSTOPPED(status)) if (WIFSTOPPED(status))
{ {
int sig = WSTOPSIG(status); int sig = WSTOPSIG(status);
if (debug_level && thread) if (debug_level && thread)
fprintf( stderr, "%04x: *signal* signal=%d\n", thread->id, sig ); fprintf( stderr, "%04x: *signal* signal=%d\n", thread->id, sig );
switch(sig) if (sig != want_sig)
{ {
case SIGSTOP: /* continue at once if not suspended */ /* ignore other signals for now */
if (thread && (thread->process->suspend + thread->suspend)) break;
/* fall through */
default: /* ignore other signals for now */
if (thread && get_thread_single_step( thread )) if (thread && get_thread_single_step( thread ))
ptrace( PTRACE_SINGLESTEP, pid, (caddr_t)1, sig ); ptrace( PTRACE_SINGLESTEP, pid, (caddr_t)1, sig );
else else
ptrace( PTRACE_CONT, pid, (caddr_t)1, sig ); ptrace( PTRACE_CONT, pid, (caddr_t)1, sig );
break;
} }
return sig; return sig;
} }
...@@ -115,13 +111,13 @@ void sigchld_handler() ...@@ -115,13 +111,13 @@ void sigchld_handler()
for (;;) for (;;)
{ {
if (!(pid = wait4( -1, &status, WUNTRACED | WNOHANG, NULL ))) break; if (!(pid = wait4( -1, &status, WUNTRACED | WNOHANG, NULL ))) break;
if (pid != -1) handle_child_status( get_thread_from_pid(pid), pid, status ); if (pid != -1) handle_child_status( get_thread_from_pid(pid), pid, status, -1 );
else break; else break;
} }
} }
/* wait for a ptraced child to get a certain signal */ /* wait for a ptraced child to get a certain signal */
void wait4_thread( struct thread *thread, int signal ) static void wait4_thread( struct thread *thread, int signal )
{ {
int res, status; int res, status;
...@@ -129,10 +125,15 @@ void wait4_thread( struct thread *thread, int signal ) ...@@ -129,10 +125,15 @@ void wait4_thread( struct thread *thread, int signal )
{ {
if ((res = wait4( thread->unix_pid, &status, WUNTRACED, NULL )) == -1) if ((res = wait4( thread->unix_pid, &status, WUNTRACED, NULL )) == -1)
{ {
perror( "wait4" ); if (errno == ECHILD) /* must have died */
{
thread->unix_pid = -1;
thread->attached = 0;
}
else perror( "wait4" );
return; return;
} }
res = handle_child_status( thread, res, status ); res = handle_child_status( thread, res, status, signal );
} while (res && res != signal); } while (res && res != signal);
} }
...@@ -176,66 +177,48 @@ void detach_thread( struct thread *thread, int sig ) ...@@ -176,66 +177,48 @@ void detach_thread( struct thread *thread, int sig )
if (thread->attached) if (thread->attached)
{ {
/* make sure it is stopped */ /* make sure it is stopped */
suspend_thread( thread, 0 ); suspend_for_ptrace( thread );
if (sig) send_thread_signal( thread, sig ); if (sig) send_thread_signal( thread, sig );
if (thread->unix_pid == -1) return; if (thread->unix_pid == -1) return;
if (debug_level) fprintf( stderr, "%04x: *detached*\n", thread->id ); if (debug_level) fprintf( stderr, "%04x: *detached*\n", thread->id );
ptrace( PTRACE_DETACH, thread->unix_pid, (caddr_t)1, sig ); ptrace( PTRACE_DETACH, thread->unix_pid, (caddr_t)1, sig );
thread->suspend = 0; /* detach makes it continue */
thread->attached = 0; thread->attached = 0;
} }
else else if (sig) send_thread_signal( thread, sig );
{
if (sig) send_thread_signal( thread, sig );
if (thread->suspend + thread->process->suspend) continue_thread( thread );
}
}
/* stop a thread (at the Unix level) */
void stop_thread( struct thread *thread )
{
/* can't stop a thread while initialisation is in progress */
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 == -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 == -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 );
} }
/* suspend a thread to allow using ptrace on it */ /* suspend a thread to allow using ptrace on it */
/* you must do a resume_thread when finished with the thread */ /* you must do a resume_after_ptrace when finished with the thread */
int suspend_for_ptrace( struct thread *thread ) int suspend_for_ptrace( struct thread *thread )
{ {
/* can't stop a thread while initialisation is in progress */
if (thread->unix_pid == -1 || !is_process_init_done(thread->process)) goto error;
if (thread->attached) if (thread->attached)
{ {
suspend_thread( thread, 0 ); send_thread_signal( thread, SIGSTOP );
wait4_thread( thread, SIGSTOP );
return 1; return 1;
} }
/* can't stop a thread while initialisation is in progress */
if (thread->unix_pid == -1 || !is_process_init_done(thread->process)) goto error;
thread->suspend++;
if (attach_thread( thread )) return 1; if (attach_thread( thread )) return 1;
thread->suspend--;
error: error:
set_error( STATUS_ACCESS_DENIED ); set_error( STATUS_ACCESS_DENIED );
return 0; return 0;
} }
/* resume a thread after we have used pthread on it */
void resume_after_ptrace( struct thread *thread )
{
if (thread->unix_pid == -1) return;
assert( thread->attached );
ptrace( get_thread_single_step(thread) ? PTRACE_SINGLESTEP : PTRACE_CONT,
thread->unix_pid, (caddr_t)1, 0 /* cancel the SIGSTOP */ );
}
/* read an int from a thread address space */ /* read an int from a thread address space */
int read_thread_int( struct thread *thread, const int *addr, int *data ) int read_thread_int( struct thread *thread, const int *addr, int *data )
{ {
errno = 0;
*data = ptrace( PTRACE_PEEKDATA, thread->unix_pid, (caddr_t)addr, 0 ); *data = ptrace( PTRACE_PEEKDATA, thread->unix_pid, (caddr_t)addr, 0 );
if ( *data == -1 && errno) if ( *data == -1 && errno)
{ {
......
...@@ -301,11 +301,18 @@ static void set_thread_info( struct thread *thread, ...@@ -301,11 +301,18 @@ static void set_thread_info( struct thread *thread,
} }
} }
/* stop a thread (at the Unix level) */
void stop_thread( struct thread *thread )
{
/* can't stop a thread while initialisation is in progress */
if (is_process_init_done(thread->process)) send_thread_signal( thread, SIGUSR1 );
}
/* suspend a thread */ /* suspend a thread */
int suspend_thread( struct thread *thread, int check_limit ) static int suspend_thread( struct thread *thread )
{ {
int old_count = thread->suspend; int old_count = thread->suspend;
if (thread->suspend < MAXIMUM_SUSPEND_COUNT || !check_limit) if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
{ {
if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread ); if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
} }
...@@ -314,16 +321,12 @@ int suspend_thread( struct thread *thread, int check_limit ) ...@@ -314,16 +321,12 @@ int suspend_thread( struct thread *thread, int check_limit )
} }
/* resume a thread */ /* resume a thread */
int resume_thread( struct thread *thread ) static int resume_thread( struct thread *thread )
{ {
int old_count = thread->suspend; int old_count = thread->suspend;
if (thread->suspend > 0) if (thread->suspend > 0)
{ {
if (!(--thread->suspend + thread->process->suspend)) if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread );
{
continue_thread( thread );
wake_thread( thread );
}
} }
return old_count; return old_count;
} }
...@@ -500,6 +503,7 @@ static void thread_timeout( void *ptr ) ...@@ -500,6 +503,7 @@ static void thread_timeout( void *ptr )
wait->user = NULL; wait->user = NULL;
if (thread->wait != wait) return; /* not the top-level wait, ignore it */ if (thread->wait != wait) return; /* not the top-level wait, ignore it */
if (thread->suspend + thread->process->suspend > 0) return; /* suspended, ignore it */
if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n", if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n",
thread->id, STATUS_TIMEOUT, cookie ); thread->id, STATUS_TIMEOUT, cookie );
...@@ -722,7 +726,7 @@ static void get_selector_entry( struct thread *thread, int entry, ...@@ -722,7 +726,7 @@ static void get_selector_entry( struct thread *thread, int entry,
if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done; if (read_thread_int( thread, addr, (int *)flags_buf ) == -1) goto done;
*flags = flags_buf[entry & 3]; *flags = flags_buf[entry & 3];
done: done:
resume_thread( thread ); resume_after_ptrace( thread );
} }
} }
...@@ -933,7 +937,7 @@ DECL_HANDLER(suspend_thread) ...@@ -933,7 +937,7 @@ DECL_HANDLER(suspend_thread)
if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
{ {
if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED ); if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED );
else reply->count = suspend_thread( thread, 1 ); else reply->count = suspend_thread( thread );
release_object( thread ); release_object( thread );
} }
} }
......
...@@ -110,8 +110,7 @@ extern struct thread *create_thread( int fd, struct process *process ); ...@@ -110,8 +110,7 @@ extern struct thread *create_thread( int fd, struct process *process );
extern struct thread *get_thread_from_id( thread_id_t id ); extern struct thread *get_thread_from_id( thread_id_t id );
extern struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access ); extern struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access );
extern struct thread *get_thread_from_pid( int pid ); extern struct thread *get_thread_from_pid( int pid );
extern int suspend_thread( struct thread *thread, int check_limit ); extern void stop_thread( struct thread *thread );
extern int resume_thread( struct thread *thread );
extern int wake_thread( struct thread *thread ); extern int wake_thread( struct thread *thread );
extern int add_queue( struct object *obj, struct wait_queue_entry *entry ); extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
extern void remove_queue( struct object *obj, struct wait_queue_entry *entry ); extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
...@@ -127,11 +126,9 @@ extern struct thread_snapshot *thread_snap( int *count ); ...@@ -127,11 +126,9 @@ extern struct thread_snapshot *thread_snap( int *count );
/* ptrace functions */ /* ptrace functions */
extern void sigchld_handler(); extern void sigchld_handler();
extern void wait4_thread( struct thread *thread, int signal );
extern void stop_thread( struct thread *thread );
extern void continue_thread( struct thread *thread );
extern void detach_thread( struct thread *thread, int sig ); extern void detach_thread( struct thread *thread, int sig );
extern int suspend_for_ptrace( struct thread *thread ); extern int suspend_for_ptrace( struct thread *thread );
extern void resume_after_ptrace( struct thread *thread );
extern int read_thread_int( struct thread *thread, const int *addr, int *data ); 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 int write_thread_int( struct thread *thread, int *addr, int data, unsigned int mask );
extern void *get_thread_ip( struct thread *thread ); extern void *get_thread_ip( struct thread *thread );
......
...@@ -195,6 +195,11 @@ static void dump_varargs_unicode_str( size_t size ) ...@@ -195,6 +195,11 @@ static void dump_varargs_unicode_str( size_t size )
static void dump_varargs_context( size_t size ) static void dump_varargs_context( size_t size )
{ {
if (!size)
{
fprintf( stderr, "{}" );
return;
}
dump_context( cur_data ); dump_context( cur_data );
remove_data( size ); remove_data( size );
} }
...@@ -202,6 +207,12 @@ static void dump_varargs_context( size_t size ) ...@@ -202,6 +207,12 @@ static void dump_varargs_context( size_t size )
static void dump_varargs_exc_event( size_t size ) static void dump_varargs_exc_event( size_t size )
{ {
const CONTEXT *ptr = cur_data; const CONTEXT *ptr = cur_data;
if (!size)
{
fprintf( stderr, "{}" );
return;
}
fprintf( stderr, "{context=" ); fprintf( stderr, "{context=" );
dump_context( ptr ); dump_context( ptr );
fprintf( stderr, ",rec=" ); fprintf( stderr, ",rec=" );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment