Add "vAttachOrWait" to debugserver, so you can implement "attach to the process if it exists OR wait for it" without race conditions. Use that in lldb.
llvm-svn: 160578
diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp
index 0a29eaa..6de893d 100644
--- a/lldb/tools/debugserver/source/DNB.cpp
+++ b/lldb/tools/debugserver/source/DNB.cpp
@@ -499,7 +499,6 @@
else
{
// We found a matching process, add it to our list
-
matching_proc_infos.push_back(proc_infos[i]);
}
}
@@ -513,6 +512,7 @@
nub_process_t
DNBProcessAttachWait (const char *waitfor_process_name,
nub_launch_flavor_t launch_flavor,
+ bool ignore_existing,
struct timespec *timeout_abstime,
useconds_t waitfor_interval,
char *err_str,
@@ -536,7 +536,12 @@
}
if (attach_token == NULL)
- num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
+ {
+ if (ignore_existing)
+ num_exclude_proc_infos = GetAllInfosMatchingName (waitfor_process_name, exclude_proc_infos);
+ else
+ num_exclude_proc_infos = 0;
+ }
DNBLogThreadedIf (LOG_PROCESS, "Waiting for '%s' to appear...\n", waitfor_process_name);
diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h
index 68df124..d206826 100644
--- a/lldb/tools/debugserver/source/DNB.h
+++ b/lldb/tools/debugserver/source/DNB.h
@@ -48,7 +48,7 @@
nub_process_t DNBProcessAttach (nub_process_t pid, struct timespec *timeout, char *err_str, size_t err_len) DNB_EXPORT;
nub_process_t DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_str, size_t err_len) DNB_EXPORT;
-nub_process_t DNBProcessAttachWait (const char *wait_name, nub_launch_flavor_t launch_flavor, struct timespec *timeout, useconds_t interval, char *err_str, size_t err_len, DNBShouldCancelCallback should_cancel = NULL, void *callback_data = NULL) DNB_EXPORT;
+nub_process_t DNBProcessAttachWait (const char *wait_name, nub_launch_flavor_t launch_flavor, bool ignore_existing, struct timespec *timeout, useconds_t interval, char *err_str, size_t err_len, DNBShouldCancelCallback should_cancel = NULL, void *callback_data = NULL) DNB_EXPORT;
// Resume a process with exact instructions on what to do with each thread:
// - If no thread actions are supplied (actions is NULL or num_actions is zero),
// then all threads are continued.
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 4b2571d..eaad18b 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -141,6 +141,7 @@
t.push_back (Packet (thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T", "Is thread alive"));
t.push_back (Packet (vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach", "Attach to a new process"));
t.push_back (Packet (vattachwait, &RNBRemote::HandlePacket_v, NULL, "vAttachWait", "Wait for a process to start up then attach to it"));
+ t.push_back (Packet (vattachorwait, &RNBRemote::HandlePacket_v, NULL, "vAttachOrWait", "Attach to the process or if it doesn't exist, wait for the process to start up then attach to it"));
t.push_back (Packet (vattachname, &RNBRemote::HandlePacket_v, NULL, "vAttachName", "Attach to an existing process by name"));
t.push_back (Packet (vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, "vCont;", "Verbose resume with thread actions"));
t.push_back (Packet (vcont_list_actions, &RNBRemote::HandlePacket_v, NULL, "vCont?", "List valid continue-with-thread-actions actions"));
@@ -169,6 +170,7 @@
t.push_back (Packet (query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL, "qRegisterInfo", "Dynamically discover remote register context information."));
t.push_back (Packet (query_shlib_notify_info_addr, &RNBRemote::HandlePacket_qShlibInfoAddr,NULL, "qShlibInfoAddr", "Returns the address that contains info needed for getting shared library notifications"));
t.push_back (Packet (query_step_packet_supported, &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported."));
+ t.push_back (Packet (query_vattachorwait_supported, &RNBRemote::HandlePacket_qVAttachOrWaitSupported,NULL, "qVAttachOrWaitSupported", "Replys with OK if the 'vAttachOrWait' packet is supported."));
t.push_back (Packet (query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
// t.push_back (Packet (query_symbol_lookup, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qSymbol", "Notify that host debugger is ready to do symbol lookups"));
t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
@@ -1302,6 +1304,13 @@
}
rnb_err_t
+RNBRemote::HandlePacket_qVAttachOrWaitSupported (const char *p)
+{
+ // We support attachOrWait meaning attach if the process exists, otherwise wait to attach.
+ return SendPacket("OK");
+}
+
+rnb_err_t
RNBRemote::HandlePacket_qThreadStopInfo (const char *p)
{
p += strlen ("qThreadStopInfo");
@@ -2678,6 +2687,31 @@
return SendPacket ("E54");
}
+static bool
+GetProcessNameFrom_vAttach (const char *&p, std::string &attach_name)
+{
+ bool return_val = true;
+ while (*p != '\0')
+ {
+ char smallbuf[3];
+ smallbuf[0] = *p;
+ smallbuf[1] = *(p + 1);
+ smallbuf[2] = '\0';
+
+ errno = 0;
+ int ch = strtoul (smallbuf, NULL, 16);
+ if (errno != 0 && ch == 0)
+ {
+ return_val = false;
+ break;
+ }
+
+ attach_name.push_back(ch);
+ p += 2;
+ }
+ return return_val;
+}
+
/*
vAttach;pid
@@ -2781,51 +2815,37 @@
{
nub_process_t attach_pid = INVALID_NUB_PROCESS;
char err_str[1024]={'\0'};
+
if (strstr (p, "vAttachWait;") == p)
{
p += strlen("vAttachWait;");
std::string attach_name;
- while (*p != '\0')
+ if (!GetProcessNameFrom_vAttach(p, attach_name))
{
- char smallbuf[3];
- smallbuf[0] = *p;
- smallbuf[1] = *(p + 1);
- smallbuf[2] = '\0';
-
- errno = 0;
- int ch = strtoul (smallbuf, NULL, 16);
- if (errno != 0 && ch == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
- }
-
- attach_name.push_back(ch);
- p += 2;
+ return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
}
+ const bool ignore_existing = true;
+ attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
- attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
-
+ }
+ else if (strstr (p, "vAttachOrWait;") == p)
+ {
+ p += strlen("vAttachOrWait;");
+ std::string attach_name;
+ if (!GetProcessNameFrom_vAttach(p, attach_name))
+ {
+ return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt");
+ }
+ const bool ignore_existing = false;
+ attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
}
else if (strstr (p, "vAttachName;") == p)
{
p += strlen("vAttachName;");
std::string attach_name;
- while (*p != '\0')
+ if (!GetProcessNameFrom_vAttach(p, attach_name))
{
- char smallbuf[3];
- smallbuf[0] = *p;
- smallbuf[1] = *(p + 1);
- smallbuf[2] = '\0';
-
- errno = 0;
- int ch = strtoul (smallbuf, NULL, 16);
- if (errno != 0 && ch == 0)
- {
- return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
- }
-
- attach_name.push_back(ch);
- p += 2;
+ return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
}
attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
@@ -2845,7 +2865,9 @@
}
}
else
+ {
return HandlePacket_UNIMPLEMENTED(p);
+ }
if (attach_pid != INVALID_NUB_PROCESS)
diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h
index 23eabdd..b10449a 100644
--- a/lldb/tools/debugserver/source/RNBRemote.h
+++ b/lldb/tools/debugserver/source/RNBRemote.h
@@ -63,6 +63,7 @@
thread_alive_p, // 'T'
vattach, // 'vAttach;pid'
vattachwait, // 'vAttachWait:XX...' where XX is one or more hex encoded process name ASCII bytes
+ vattachorwait, // 'vAttachOrWait:XX...' where XX is one or more hex encoded process name ASCII bytes
vattachname, // 'vAttachName:XX...' where XX is one or more hex encoded process name ASCII bytes
vcont, // 'vCont'
vcont_list_actions, // 'vCont?'
@@ -91,6 +92,7 @@
query_register_info, // 'qRegisterInfo'
query_shlib_notify_info_addr, // 'qShlibInfoAddr'
query_step_packet_supported, // 'qStepPacketSupported'
+ query_vattachorwait_supported, // 'qVAttachOrWaitSupported'
query_host_info, // 'qHostInfo'
pass_signals_to_inferior, // 'QPassSignals'
start_noack_mode, // 'QStartNoAckMode'
@@ -164,6 +166,7 @@
rnb_err_t HandlePacket_qRegisterInfo (const char *p);
rnb_err_t HandlePacket_qShlibInfoAddr (const char *p);
rnb_err_t HandlePacket_qStepPacketSupported (const char *p);
+ rnb_err_t HandlePacket_qVAttachOrWaitSupported (const char *p);
rnb_err_t HandlePacket_qThreadInfo (const char *p);
rnb_err_t HandlePacket_qThreadExtraInfo (const char *p);
rnb_err_t HandlePacket_qThreadStopInfo (const char *p);
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index fe98848..6f3ba70 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -105,7 +105,7 @@
err = remote->HandleReceivedPacket (&type);
// check if we tried to attach to a process
- if (type == RNBRemote::vattach || type == RNBRemote::vattachwait)
+ if (type == RNBRemote::vattach || type == RNBRemote::vattachwait || type == RNBRemote::vattachorwait)
{
if (err == rnb_success)
return eRNBRunLoopModeInferiorExecuting;
@@ -1319,8 +1319,8 @@
}
ctx.SetLaunchFlavor(launch_flavor);
-
- nub_process_t pid = DNBProcessAttachWait (waitfor_pid_name.c_str(), launch_flavor, timeout_ptr, waitfor_interval, err_str, sizeof(err_str));
+ bool ignore_existing = false;
+ nub_process_t pid = DNBProcessAttachWait (waitfor_pid_name.c_str(), launch_flavor, ignore_existing, timeout_ptr, waitfor_interval, err_str, sizeof(err_str));
g_pid = pid;
if (pid == INVALID_NUB_PROCESS)