Hi vharron, clayborg,

SBTarget::Attach, SBTarget::AttachToProcessWithID and 
SBTarget::AttachToProcessWithName use the same core logic - extracted it into 
new static method SBTarget::AttachToProcess.
Made SBTarget::AttachToProcess to support remote attach if a platform is 
available and can debug a process - this makes TestHelloWorld to pass in case 
of remote platform on Linux (test is passing when test suite and platform are 
running on the same machine, fully distributed test run requires further 
investigation).

http://reviews.llvm.org/D7471

Files:
  include/lldb/API/SBTarget.h
  source/API/SBTarget.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/lldb/API/SBTarget.h
===================================================================
--- include/lldb/API/SBTarget.h
+++ include/lldb/API/SBTarget.h
@@ -914,6 +914,9 @@
     void
     SetSP (const lldb::TargetSP& target_sp);
 
+    static lldb::ProcessSP
+    AttachToProcess (lldb_private::ProcessAttachInfo &attach_info, lldb_private::Target &target, SBListener &listener, lldb_private::Error &error);
+
 
 private:
     //------------------------------------------------------------------
Index: source/API/SBTarget.cpp
===================================================================
--- source/API/SBTarget.cpp
+++ source/API/SBTarget.cpp
@@ -613,81 +613,43 @@
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     SBProcess sb_process;
-    ProcessSP process_sp;
     TargetSP target_sp(GetSP());
 
     if (log)
         log->Printf ("SBTarget(%p)::Attach (sb_attach_info, error)...",
                      static_cast<void*>(target_sp.get()));
 
     if (target_sp)
     {
-        Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
-        StateType state = eStateInvalid;
-        process_sp = target_sp->GetProcessSP();
-        if (process_sp)
+        ProcessAttachInfo &attach_info = sb_attach_info.ref();
+        if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid())
         {
-            state = process_sp->GetState();
-
-            if (process_sp->IsAlive() && state != eStateConnected)
+            PlatformSP platform_sp = target_sp->GetPlatform();
+            // See if we can pre-verify if a process exists or not
+            if (platform_sp && platform_sp->IsConnected())
             {
-                if (state == eStateAttaching)
-                    error.SetErrorString ("process attach is in progress");
+                lldb::pid_t attach_pid = attach_info.GetProcessID();
+                ProcessInstanceInfo instance_info;
+                if (platform_sp->GetProcessInfo(attach_pid, instance_info))
+                {
+                    attach_info.SetUserID(instance_info.GetEffectiveUserID());
+                }
                 else
-                    error.SetErrorString ("a process is already being debugged");
-                if (log)
-                    log->Printf ("SBTarget(%p)::Attach (...) => error %s",
-                                 static_cast<void*>(target_sp.get()),
-                                 error.GetCString());
-                return sb_process;
-            }
-        }
-
-        if (state != eStateConnected)
-            process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
-
-        if (process_sp)
-        {
-            ProcessAttachInfo &attach_info = sb_attach_info.ref();
-            if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid())
-            {
-                PlatformSP platform_sp = target_sp->GetPlatform();
-                // See if we can pre-verify if a process exists or not
-                if (platform_sp && platform_sp->IsConnected())
                 {
-                    lldb::pid_t attach_pid = attach_info.GetProcessID();
-                    ProcessInstanceInfo instance_info;
-                    if (platform_sp->GetProcessInfo(attach_pid, instance_info))
+                    error.ref().SetErrorStringWithFormat("no process found with process ID %" PRIu64, attach_pid);
+                    if (log)
                     {
-                        attach_info.SetUserID(instance_info.GetEffectiveUserID());
-                    }
-                    else
-                    {
-                        error.ref().SetErrorStringWithFormat("no process found with process ID %" PRIu64, attach_pid);
-                        if (log)
-                        {
-                            log->Printf ("SBTarget(%p)::Attach (...) => error %s",
-                                         static_cast<void*>(target_sp.get()), error.GetCString());
-                        }
-                        return sb_process;
+                        log->Printf ("SBTarget(%p)::Attach (...) => error %s",
+                                     static_cast<void*>(target_sp.get()), error.GetCString());
                     }
+                    return sb_process;
                 }
             }
-            error.SetError (process_sp->Attach (attach_info));
-            if (error.Success())
-            {
-                sb_process.SetSP (process_sp);
-                // If we are doing synchronous mode, then wait for the
-                // process to stop!
-                if (target_sp->GetDebugger().GetAsyncExecution () == false)
-                    process_sp->WaitForProcessToStop (NULL);
-            }
-        }
-        else
-        {
-            error.SetErrorString ("unable to create lldb_private::Process");
         }
+        SBListener noop_listener;
+        const auto process_sp = AttachToProcess (attach_info, *target_sp, noop_listener, error.ref());
+        if (error.Success () && process_sp)
+            sb_process.SetSP (process_sp);
     }
     else
     {
@@ -697,7 +659,7 @@
     if (log)
         log->Printf ("SBTarget(%p)::Attach (...) => SBProcess(%p)",
                      static_cast<void*>(target_sp.get()),
-                     static_cast<void*>(process_sp.get()));
+                     static_cast<void*>(sb_process.GetSP().get()));
 
     return sb_process;
 }
@@ -726,87 +688,37 @@
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     SBProcess sb_process;
-    ProcessSP process_sp;
     TargetSP target_sp(GetSP());
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToProcessWithID (listener, pid=%" PRId64 ", error)...",
-                     static_cast<void*>(target_sp.get()), pid);
+        log->Printf ("SBTarget(%p)::%s (listener, pid=%" PRId64 ", error)...",
+                     static_cast<void*>(target_sp.get()),
+                     __FUNCTION__,
+                     pid);
 
     if (target_sp)
     {
-        Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
-        StateType state = eStateInvalid;
-        process_sp = target_sp->GetProcessSP();
-        if (process_sp)
-        {
-            state = process_sp->GetState();
+        ProcessAttachInfo attach_info;
+        attach_info.SetProcessID (pid);
+        if (listener.IsValid())
+            attach_info.SetListener(listener.GetSP());
 
-            if (process_sp->IsAlive() && state != eStateConnected)
-            {
-                if (state == eStateAttaching)
-                    error.SetErrorString ("process attach is in progress");
-                else
-                    error.SetErrorString ("a process is already being debugged");
-                return sb_process;
-            }
-        }
+        ProcessInstanceInfo instance_info;
+        if (target_sp->GetPlatform ()->GetProcessInfo (pid, instance_info))
+            attach_info.SetUserID (instance_info.GetEffectiveUserID ());
+        const auto process_sp = AttachToProcess (attach_info, *target_sp, listener, error.ref());
 
-        if (state == eStateConnected)
-        {
-            // If we are already connected, then we have already specified the
-            // listener, so if a valid listener is supplied, we need to error out
-            // to let the client know.
-            if (listener.IsValid())
-            {
-                error.SetErrorString ("process is connected and already has a listener, pass empty listener");
-                return sb_process;
-            }
-        }
-        else
-        {
-            if (listener.IsValid())
-                process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
-            else
-                process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
-        }
-        if (process_sp)
-        {
+        if (error.Success () && process_sp)
             sb_process.SetSP (process_sp);
-
-            ProcessAttachInfo attach_info;
-            attach_info.SetProcessID (pid);
-
-            PlatformSP platform_sp = target_sp->GetPlatform();
-            ProcessInstanceInfo instance_info;
-            if (platform_sp->GetProcessInfo(pid, instance_info))
-            {
-                attach_info.SetUserID(instance_info.GetEffectiveUserID());
-            }
-            error.SetError (process_sp->Attach (attach_info));            
-            if (error.Success())
-            {
-                // If we are doing synchronous mode, then wait for the
-                // process to stop!
-                if (target_sp->GetDebugger().GetAsyncExecution () == false)
-                    process_sp->WaitForProcessToStop (NULL);
-            }
-        }
-        else
-        {
-            error.SetErrorString ("unable to create lldb_private::Process");
-        }
     }
     else
-    {
         error.SetErrorString ("SBTarget is invalid");
-    }
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToProcessWithID (...) => SBProcess(%p)",
-                     static_cast<void*>(target_sp.get()),
-                     static_cast<void*>(process_sp.get()));
+        log->Printf ("SBTarget(%p)::%s (...) => SBProcess(%p)",
+                     static_cast<void*>(target_sp.get ()),
+                     __FUNCTION__,
+                     static_cast<void*>(sb_process.GetSP().get ()));
     return sb_process;
 }
 
@@ -822,82 +734,35 @@
     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
 
     SBProcess sb_process;
-    ProcessSP process_sp;
     TargetSP target_sp(GetSP());
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToProcessWithName (listener, name=%s, wait_for=%s, error)...",
-                     static_cast<void*>(target_sp.get()), name,
+        log->Printf ("SBTarget(%p)::%s (listener, name=%s, wait_for=%s, error)...",
+                     static_cast<void*>(target_sp.get()),
+                     __FUNCTION__,
+                     name,
                      wait_for ? "true" : "false");
 
     if (name && target_sp)
     {
-        Mutex::Locker api_locker (target_sp->GetAPIMutex());
-
-        StateType state = eStateInvalid;
-        process_sp = target_sp->GetProcessSP();
-        if (process_sp)
-        {
-            state = process_sp->GetState();
-
-            if (process_sp->IsAlive() && state != eStateConnected)
-            {
-                if (state == eStateAttaching)
-                    error.SetErrorString ("process attach is in progress");
-                else
-                    error.SetErrorString ("a process is already being debugged");
-                return sb_process;
-            }
-        }
-
-        if (state == eStateConnected)
-        {
-            // If we are already connected, then we have already specified the
-            // listener, so if a valid listener is supplied, we need to error out
-            // to let the client know.
-            if (listener.IsValid())
-            {
-                error.SetErrorString ("process is connected and already has a listener, pass empty listener");
-                return sb_process;
-            }
-        }
-        else
-        {
-            if (listener.IsValid())
-                process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
-            else
-                process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
-        }
+        ProcessAttachInfo attach_info;
+        attach_info.GetExecutableFile().SetFile(name, false);
+        attach_info.SetWaitForLaunch(wait_for);
+        if (listener.IsValid())
+            attach_info.SetListener(listener.GetSP());
 
-        if (process_sp)
-        {
+        const auto process_sp = AttachToProcess (attach_info, *target_sp, listener, error.ref());
+        if (error.Success () && process_sp)
             sb_process.SetSP (process_sp);
-            ProcessAttachInfo attach_info;
-            attach_info.GetExecutableFile().SetFile(name, false);
-            attach_info.SetWaitForLaunch(wait_for);
-            error.SetError (process_sp->Attach (attach_info));
-            if (error.Success())
-            {
-                // If we are doing synchronous mode, then wait for the
-                // process to stop!
-                if (target_sp->GetDebugger().GetAsyncExecution () == false)
-                    process_sp->WaitForProcessToStop (NULL);
-            }
-        }
-        else
-        {
-            error.SetErrorString ("unable to create lldb_private::Process");
-        }
     }
     else
-    {
         error.SetErrorString ("SBTarget is invalid");
-    }
 
     if (log)
-        log->Printf ("SBTarget(%p)::AttachToPorcessWithName (...) => SBProcess(%p)",
+        log->Printf ("SBTarget(%p)::%s (...) => SBProcess(%p)",
                      static_cast<void*>(target_sp.get()),
-                     static_cast<void*>(process_sp.get()));
+                     __FUNCTION__,
+                     static_cast<void*>(sb_process.GetSP().get()));
     return sb_process;
 }
 
@@ -2679,3 +2544,81 @@
     return 0;
 }
 
+ProcessSP
+SBTarget::AttachToProcess (ProcessAttachInfo &attach_info, Target &target, SBListener &listener, Error &error)
+{
+    error.Clear();
+
+    Mutex::Locker api_locker (target.GetAPIMutex ());
+
+    StateType state = eStateInvalid;
+    auto process_sp = target.GetProcessSP ();
+    if (process_sp)
+    {
+        state = process_sp->GetState ();
+
+        if (process_sp->IsAlive () && state != eStateConnected)
+        {
+            if (state == eStateAttaching)
+                error.SetErrorString ("process attach is in progress");
+            else
+                error.SetErrorString ("a process is already being debugged");
+            return process_sp;
+        }
+    }
+
+    ListenerSP hijack_listener_sp (new Listener ("lldb.SBTarget.AttachToProcess.attach.hijack"));
+    attach_info.SetHijackListener (hijack_listener_sp);
+
+    if (state == eStateConnected)
+    {
+        // If we are already connected, then we have already specified the
+        // listener, so if a valid listener is supplied, we need to error out
+        // to let the client know.
+        if (listener.IsValid ())
+        {
+            error.SetErrorString ("process is connected and already has a listener, pass empty listener");
+            return process_sp;
+        }
+        error = process_sp->Attach (attach_info);
+    }
+    else
+    {
+        const auto platform_sp = target.GetPlatform ();
+        if (platform_sp != nullptr && platform_sp->CanDebugProcess ())
+        {
+            process_sp = platform_sp->Attach (attach_info, target.GetDebugger (), &target, error);
+        }
+        else
+        {
+            process_sp = target.CreateProcess (
+                (listener.IsValid ()) ? listener.ref () : target.GetDebugger ().GetListener (), nullptr, nullptr);
+            if (process_sp)
+            {
+                process_sp->HijackProcessEvents (hijack_listener_sp.get());
+                error = process_sp->Attach (attach_info);
+            }
+            else
+                error.SetErrorString ("failed to create lldb_private::Process");
+        }
+    }
+
+    if (error.Success () && process_sp)
+    {
+        StreamString stream;
+        StateType state = process_sp->WaitForProcessToStop (nullptr, nullptr, false, attach_info.GetHijackListener ().get (), &stream);
+
+        process_sp->RestoreProcessEvents ();
+
+        if (state != eStateStopped)
+        {
+            const char *exit_desc = process_sp->GetExitDescription ();
+            if (exit_desc)
+                error.SetErrorStringWithFormat ("attach failed: %s", exit_desc);
+            else
+              error.SetErrorStringWithFormat ("attach failed: process did not stop (no such process or permission problem?)");
+            process_sp->Destroy ();
+        }
+    }
+    return process_sp;
+}
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -1448,6 +1448,7 @@
     else if (m_is_platform)
     {
         pid = m_process_launch_info.GetProcessID ();
+        m_process_launch_info.Clear ();
     }
     else
         return SendUnimplementedResponse (packet.GetStringRef ().c_str ());
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to