virtual lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url,
llvm::StringRef plugin_name,
- lldb_private::Debugger &debugger,
- lldb_private::Target *target,
- lldb_private::Status &error);
+ Debugger &debugger, Target *target,
+ Status &error);
+
+ virtual lldb::ProcessSP
+ ConnectProcessSynchronous(llvm::StringRef connect_url,
+ llvm::StringRef plugin_name, Debugger &debugger,
+ Stream &stream, Target *target, Status &error);
/// Attach to an existing process using a process ID.
///
}
protected:
+ /// Private implementation of connecting to a process. If the stream is set
+ /// we connect synchronously.
+ lldb::ProcessSP DoConnectProcess(llvm::StringRef connect_url,
+ llvm::StringRef plugin_name,
+ Debugger &debugger, Stream *stream,
+ Target *target, Status &error);
bool m_is_host;
// Set to true when we are able to actually set the OS version while being
// connected. For remote platforms, we might set the version ahead of time
Status error;
Debugger &debugger = GetDebugger();
PlatformSP platform_sp = m_interpreter.GetPlatform(true);
- ProcessSP process_sp = platform_sp->ConnectProcess(
- command.GetArgumentAtIndex(0), plugin_name, debugger,
- debugger.GetSelectedTarget().get(), error);
+ ProcessSP process_sp =
+ debugger.GetAsyncExecution()
+ ? platform_sp->ConnectProcess(
+ command.GetArgumentAtIndex(0), plugin_name, debugger,
+ debugger.GetSelectedTarget().get(), error)
+ : platform_sp->ConnectProcessSynchronous(
+ command.GetArgumentAtIndex(0), plugin_name, debugger,
+ result.GetOutputStream(), debugger.GetSelectedTarget().get(),
+ error);
if (error.Fail() || process_sp == nullptr) {
result.AppendError(error.AsCString("Error connecting to the process"));
result.SetStatus(eReturnStatusFailed);
#include <memory>
#include <vector>
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
-
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
// Define these constants from POSIX mman.h rather than include the file so
// that they will be correct even when compiled on Linux.
lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url,
llvm::StringRef plugin_name,
- lldb_private::Debugger &debugger,
- lldb_private::Target *target,
- lldb_private::Status &error) {
+ Debugger &debugger, Target *target,
+ Status &error) {
+ return DoConnectProcess(connect_url, plugin_name, debugger, nullptr, target,
+ error);
+}
+
+lldb::ProcessSP Platform::ConnectProcessSynchronous(
+ llvm::StringRef connect_url, llvm::StringRef plugin_name,
+ Debugger &debugger, Stream &stream, Target *target, Status &error) {
+ return DoConnectProcess(connect_url, plugin_name, debugger, &stream, target,
+ error);
+}
+
+lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url,
+ llvm::StringRef plugin_name,
+ Debugger &debugger, Stream *stream,
+ Target *target, Status &error) {
error.Clear();
if (!target) {
lldb::ProcessSP process_sp =
target->CreateProcess(debugger.GetListener(), plugin_name, nullptr);
+
if (!process_sp)
return nullptr;
+ // If this private method is called with a stream we are synchronous.
+ const bool synchronous = stream != nullptr;
+
+ ListenerSP listener_sp(
+ Listener::MakeListener("lldb.Process.ConnectProcess.hijack"));
+ if (synchronous)
+ process_sp->HijackProcessEvents(listener_sp);
+
error = process_sp->ConnectRemote(connect_url);
- if (error.Fail())
+ if (error.Fail()) {
+ if (synchronous)
+ process_sp->RestoreProcessEvents();
return nullptr;
+ }
+
+ if (synchronous) {
+ EventSP event_sp;
+ process_sp->WaitForProcessToStop(llvm::None, &event_sp, true, listener_sp,
+ nullptr);
+ process_sp->RestoreProcessEvents();
+ bool pop_process_io_handler = false;
+ Process::HandleProcessStateChangedEvent(event_sp, stream,
+ pop_process_io_handler);
+ }
return process_sp;
}
--- /dev/null
+import lldb
+import binascii
+import os
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+
+class TestProcessConnect(GDBRemoteTestBase):
+ def test_gdb_remote_sync(self):
+ """Test the gdb-remote command in synchronous mode"""
+ try:
+ self.dbg.SetAsync(False)
+ self.expect("gdb-remote %d" % self.server.port,
+ substrs=['Process', 'stopped'])
+ finally:
+ self.dbg.GetSelectedPlatform().DisconnectRemote()
+
+ def test_gdb_remote_async(self):
+ """Test the gdb-remote command in asynchronous mode"""
+ try:
+ self.dbg.SetAsync(True)
+ self.expect("gdb-remote %d" % self.server.port,
+ matching=False,
+ substrs=['Process', 'stopped'])
+ lldbutil.expect_state_changes(self, self.dbg.GetListener(),
+ self.process(), [lldb.eStateStopped])
+ finally:
+ self.dbg.GetSelectedPlatform().DisconnectRemote()
+
+ def test_process_connect_sync(self):
+ """Test the gdb-remote command in synchronous mode"""
+ try:
+ self.dbg.SetAsync(False)
+ self.expect("process connect connect://localhost:%d" %
+ self.server.port,
+ substrs=['Process', 'stopped'])
+ finally:
+ self.dbg.GetSelectedPlatform().DisconnectRemote()
+
+ def test_process_connect_async(self):
+ """Test the gdb-remote command in asynchronous mode"""
+ try:
+ self.dbg.SetAsync(True)
+ self.expect("process connect connect://localhost:%d" %
+ self.server.port,
+ matching=False,
+ substrs=['Process', 'stopped'])
+ lldbutil.expect_state_changes(self, self.dbg.GetListener(),
+ self.process(), [lldb.eStateStopped])
+ finally:
+ self.dbg.GetSelectedPlatform().DisconnectRemote()