summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
diff options
context:
space:
mode:
authorTodd Fiala <tfiala@google.com>2014-01-23 22:05:44 +0000
committerTodd Fiala <tfiala@google.com>2014-01-23 22:05:44 +0000
commit403edc5c57b608585b94c93a648333231a9c68c7 (patch)
treea3e7f3f652ab7e5822046300a579766f6e3f1602 /lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
parenta786e53903c08e0d0f04c92b0f32e83005e252ce (diff)
downloadbcm5719-llvm-403edc5c57b608585b94c93a648333231a9c68c7.tar.gz
bcm5719-llvm-403edc5c57b608585b94c93a648333231a9c68c7.zip
Move process launching into GDBRemoteCommunicationServer.
lldb-gdbserver was launching the commandline-specified launch process directly, without GDBRemoteCommunicationServer knowing anything about it. As GDBRemoteCommunicationServer is the piece that manages and knows about processes that the gdb remote protocol discusses with the client end, it is important that it know about launched processes. This change also implements the k gdb remote protocol message, having it kill all known spawned processes when it is received. (Note: in lldb-gdbserver, the spawned processes are not properly monitored yet. The response to the k packet will complain that spawned processes do not really appear to be getting killed even if they are. This will get addressed soon.) llvm-svn: 199945
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp163
1 files changed, 132 insertions, 31 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index bed8852b7a0..568997f2ead 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -143,6 +143,10 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
packet_result = Handle_qKillSpawnedProcess (packet);
break;
+ case StringExtractorGDBRemote::eServerPacketType_k:
+ packet_result = Handle_k (packet);
+ break;
+
case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
packet_result = Handle_qLaunchSuccess (packet);
break;
@@ -271,6 +275,38 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
return packet_result == PacketResult::Success;
}
+lldb_private::Error
+GDBRemoteCommunicationServer::LaunchProcess (const char *const args[], int argc, unsigned int launch_flags)
+{
+ if ((argc < 1) || !args || !args[0] || !args[0][0])
+ lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
+
+ // Launch the program specified in args
+ m_process_launch_info.Clear ();
+ m_process_launch_info.SetArguments (const_cast<const char**> (args), true);
+ m_process_launch_info.GetFlags ().Set (launch_flags);
+
+ lldb_private::Error error = Host::LaunchProcess (m_process_launch_info);
+ if (!error.Success ())
+ {
+ fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, args[0]);
+ return error;
+ }
+
+ printf ("Launched '%s' as process %" PRIu64 "...\n", args[0], m_process_launch_info.GetProcessID());
+
+ // add to list of spawned processes. On an lldb-gdbserver, we
+ // would expect there to be only one.
+ lldb::pid_t pid;
+ if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID )
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(pid);
+ }
+
+ return error;
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
{
@@ -897,57 +933,122 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
#endif
}
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+bool
+GDBRemoteCommunicationServer::KillSpawnedProcess (lldb::pid_t pid)
{
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
-
- if (m_is_platform)
+ // make sure we know about this process
{
- packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return false;
+ }
- lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+ // first try a SIGTERM (standard kill)
+ Host::Kill (pid, SIGTERM);
- // Scope for locker
+ // check if that worked
+ for (size_t i=0; i<10; ++i)
+ {
{
Mutex::Locker locker (m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendErrorResponse (10);
+ {
+ // it is now killed
+ return true;
+ }
}
- Host::Kill (pid, SIGTERM);
+ usleep (10000);
+ }
- for (size_t i=0; i<10; ++i)
+ // check one more time after the final usleep
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // the launched process still lives. Now try killling it again,
+ // this time with an unblockable signal.
+ Host::Kill (pid, SIGKILL);
+
+ for (size_t i=0; i<10; ++i)
+ {
{
- // Scope for locker
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
{
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendOKResponse();
+ // it is now killed
+ return true;
}
- usleep (10000);
}
+ usleep (10000);
+ }
- // Scope for locker
+ // check one more time after the final usleep
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // no luck - the process still lives
+ return false;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+ // verify that we know anything about this pid.
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
{
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendOKResponse();
+ // not a pid we know about
+ return SendErrorResponse (10);
}
- Host::Kill (pid, SIGKILL);
+ }
+
+ // go ahead and attempt to kill the spawned process
+ if (KillSpawnedProcess (pid))
+ return SendOKResponse ();
+ else
+ return SendErrorResponse (11);
+}
- for (size_t i=0; i<10; ++i)
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_k (StringExtractorGDBRemote &packet)
+{
+ // ignore for now if we're lldb_platform
+ if (m_is_platform)
+ return SendUnimplementedResponse (packet.GetStringRef().c_str());
+
+ // shutdown all spawned processes
+ std::set<lldb::pid_t> spawned_pids_copy;
+
+ // copy pids
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ());
+ }
+
+ // nuke the spawned processes
+ for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it)
+ {
+ lldb::pid_t spawned_pid = *it;
+ if (!KillSpawnedProcess (spawned_pid))
{
- // Scope for locker
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendOKResponse();
- }
- usleep (10000);
+ fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid);
}
}
- return SendErrorResponse (11);
+
+ // TODO figure out how to shut down gracefully at this point
+ return SendOKResponse ();
}
GDBRemoteCommunication::PacketResult
OpenPOWER on IntegriCloud