From 5f258c68f30fd958a15ad143272b552fdc2cde5c Mon Sep 17 00:00:00 2001
From: Alexandre Julliard <julliard@winehq.org>
Date: Sat, 14 Jul 2001 00:50:30 +0000
Subject: [PATCH] Backed out the suspend_process_for_ptrace change. Fixed a
 couple of races in ptrace code.

---
 server/debugger.c |  2 +-
 server/file.c     |  1 +
 server/process.c  | 15 ---------------
 server/process.h  |  1 -
 server/ptrace.c   | 21 ++++++++++++---------
 5 files changed, 14 insertions(+), 26 deletions(-)

diff --git a/server/debugger.c b/server/debugger.c
index 377b4b30dbf..bde34444f64 100644
--- a/server/debugger.c
+++ b/server/debugger.c
@@ -411,7 +411,7 @@ 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_for_ptrace( process );
+    suspend_process( process );
 
     /* we must have been able to attach all threads */
     for (thread = process->thread_list; thread; thread = thread->proc_next)
diff --git a/server/file.c b/server/file.c
index 6b83915e210..4c5c5f8e8d8 100644
--- a/server/file.c
+++ b/server/file.c
@@ -319,6 +319,7 @@ void file_set_error(void)
     case EBADF:     set_error( STATUS_INVALID_HANDLE ); break;
     case ENOSPC:    set_error( STATUS_DISK_FULL ); break;
     case EACCES:
+    case ESRCH:
     case EPERM:     set_error( STATUS_ACCESS_DENIED ); break;
     case EROFS:     set_error( STATUS_MEDIA_WRITE_PROTECTED ); break;
     case EBUSY:     set_error( STATUS_FILE_LOCK_CONFLICT ); break;
diff --git a/server/process.c b/server/process.c
index fbead288ab4..39f40e6f301 100644
--- a/server/process.c
+++ b/server/process.c
@@ -491,21 +491,6 @@ 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 6d4a57a8a64..fb272c79339 100644
--- a/server/process.h
+++ b/server/process.h
@@ -81,7 +81,6 @@ 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 );
diff --git a/server/ptrace.c b/server/ptrace.c
index 2433732da34..a36bed7f762 100644
--- a/server/ptrace.c
+++ b/server/ptrace.c
@@ -42,20 +42,17 @@
 #define PTRACE_POKEDATA PT_WRITE_D
 #endif
 
-#ifdef HAVE_SYS_PTRACE_H
-static const int use_ptrace = 1;  /* set to 0 to disable ptrace */
-#else
-static const int use_ptrace = 0;
-
+#ifndef HAVE_SYS_PTRACE_H
 #define PT_CONTINUE 0
 #define PT_ATTACH   1
 #define PT_DETACH   2
 #define PT_READ_D   3
 #define PT_WRITE_D  4
 #define PT_STEP     5
+inline static int ptrace(int req, ...) { errno = EPERM; return -1; /*FAIL*/ }
+#endif  /* HAVE_SYS_PTRACE_H */
 
-static int ptrace(int req, ...) { return -1; /*FAIL*/ }
-#endif
+static const int use_ptrace = 1;  /* set to 0 to disable ptrace */
 
 /* handle a status returned by wait4 */
 static int handle_child_status( struct thread *thread, int pid, int status )
@@ -129,7 +126,12 @@ void wait4_thread( struct thread *thread, int signal )
 static int attach_thread( struct thread *thread )
 {
     /* this may fail if the client is already being debugged */
-    if (!use_ptrace || (ptrace( PTRACE_ATTACH, thread->unix_pid, 0, 0 ) == -1)) return 0;
+    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 */
+        return 0;
+    }
     if (debug_level) fprintf( stderr, "%08x: *attached*\n", (unsigned int)thread );
     thread->attached = 1;
     wait4_thread( thread, SIGSTOP );
@@ -143,10 +145,11 @@ void detach_thread( struct thread *thread, int sig )
     if (thread->attached)
     {
         /* make sure it is stopped */
-        if (!(thread->suspend + thread->process->suspend)) stop_thread( thread );
+        suspend_thread( thread, 0 );
         if (sig) kill( thread->unix_pid, sig );
         if (debug_level) fprintf( stderr, "%08x: *detached*\n", (unsigned int)thread );
         ptrace( PTRACE_DETACH, thread->unix_pid, (caddr_t)1, sig );
+        thread->suspend = 0;  /* detach makes it continue */
         thread->attached = 0;
     }
     else
-- 
GitLab