diff --git a/server/context_i386.c b/server/context_i386.c index 50deb049fe7..87d1da1c7c6 100644 --- a/server/context_i386.c +++ b/server/context_i386.c @@ -150,11 +150,10 @@ static void set_thread_context( struct thread *thread, unsigned int flags, CONTE if (flags & CONTEXT_FULL) { struct kernel_user_regs_struct regs; - if (((flags | CONTEXT_i386) & CONTEXT_FULL) != CONTEXT_FULL) - { - /* need to preserve some registers */ - if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error; - } + + /* need to preserve some registers (at a minimum orig_eax must always be preserved) */ + if (ptrace( PTRACE_GETREGS, pid, 0, ®s ) == -1) goto error; + if (flags & CONTEXT_INTEGER) { regs.eax = context->Eax; diff --git a/server/debugger.c b/server/debugger.c index eb86efebdd8..377b4b30dbf 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -411,13 +411,12 @@ static int debugger_attach( struct process *process, struct thread *debugger ) for (thread = debugger; thread; thread = thread->process->debugger) if (thread->process == process) goto error; - suspend_process( process ); + suspend_process_for_ptrace( process ); /* we must have been able to attach all threads */ for (thread = process->thread_list; thread; thread = thread->proc_next) if (!thread->attached) { - fprintf( stderr, "%p not attached\n", thread ); resume_process( process ); goto error; } diff --git a/server/process.c b/server/process.c index 39f40e6f301..fbead288ab4 100644 --- a/server/process.c +++ b/server/process.c @@ -491,6 +491,21 @@ void suspend_process( struct process *process ) } } +/* suspend all the threads of a process to allow using ptrace on it*/ +void suspend_process_for_ptrace( struct process *process ) +{ + if (!process->suspend++) + { + struct thread *thread = process->thread_list; + for (; thread; thread = thread->proc_next) + { + if (thread->suspend) continue; + if (suspend_for_ptrace( thread )) + thread->suspend--; /* since the process is suspended, not the thread */ + } + } +} + /* resume all the threads of a process */ void resume_process( struct process *process ) { diff --git a/server/process.h b/server/process.h index fb272c79339..6d4a57a8a64 100644 --- a/server/process.h +++ b/server/process.h @@ -81,6 +81,7 @@ extern void add_process_thread( struct process *process, extern void remove_process_thread( struct process *process, struct thread *thread ); extern void suspend_process( struct process *process ); +extern void suspend_process_for_ptrace( struct process *process ); extern void resume_process( struct process *process ); extern void kill_process( struct process *process, struct thread *skip, int exit_code ); extern void kill_debugged_processes( struct thread *debugger, int exit_code );