mgorny updated this revision to Diff 444296.
mgorny added a comment.
Rebased.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D128932/new/
https://reviews.llvm.org/D128932
Files:
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
lldb/test/API/tools/lldb-server/main.cpp
Index: lldb/test/API/tools/lldb-server/main.cpp
===================================================================
--- lldb/test/API/tools/lldb-server/main.cpp
+++ lldb/test/API/tools/lldb-server/main.cpp
@@ -224,6 +224,8 @@
int return_value = 0;
#if !defined(_WIN32)
+ bool is_child = false;
+
// Set the signal handler.
sig_t sig_result = signal(SIGALRM, signal_handler);
if (sig_result == SIG_ERR) {
@@ -324,10 +326,32 @@
func_p();
#if !defined(_WIN32) && !defined(TARGET_OS_WATCH) && !defined(TARGET_OS_TV)
} else if (arg == "fork") {
- assert (fork() != -1);
+ pid_t fork_pid = fork();
+ assert(fork_pid != -1);
+ is_child = fork_pid == 0;
} else if (arg == "vfork") {
if (vfork() == 0)
_exit(0);
+ } else if (consume_front(arg, "process:sync:")) {
+ // this is only valid after fork
+ const char *filenames[] = {"parent", "child"};
+ std::string my_file = arg + "." + filenames[is_child];
+ std::string other_file = arg + "." + filenames[!is_child];
+
+ // indicate that we're ready
+ FILE *f = fopen(my_file.c_str(), "w");
+ assert(f);
+ fclose(f);
+
+ // wait for the other process to be ready
+ for (int i = 0; i < 5; ++i) {
+ f = fopen(other_file.c_str(), "r");
+ if (f)
+ break;
+ std::this_thread::sleep_for(std::chrono::milliseconds(125 * (1<<i)));
+ }
+ assert(f);
+ fclose(f);
#endif
} else if (consume_front(arg, "thread:new")) {
std::promise<void> promise;
Index: lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
===================================================================
--- lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
+++ lldb/test/API/tools/lldb-server/TestGdbRemoteForkNonStop.py
@@ -1,3 +1,5 @@
+import binascii
+
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
@@ -112,3 +114,33 @@
def test_vCont_interspersed_nonstop(self):
self.resume_one_test(run_order=["parent", "child", "parent", "child"],
use_vCont=True, nonstop=True)
+
+ @add_test_categories(["fork"])
+ def test_c_both_nonstop(self):
+ lock1 = self.getBuildArtifact("lock1")
+ lock2 = self.getBuildArtifact("lock2")
+ parent_pid, parent_tid, child_pid, child_tid = (
+ self.start_fork_test(["fork", "process:sync:" + lock1, "print-pid",
+ "process:sync:" + lock2, "stop"],
+ nonstop=True))
+
+ self.test_sequence.add_log_lines([
+ "read packet: $Hcp{}.{}#00".format(parent_pid, parent_tid),
+ "send packet: $OK#00",
+ "read packet: $c#00",
+ "send packet: $OK#00",
+ "read packet: $Hcp{}.{}#00".format(child_pid, child_tid),
+ "send packet: $OK#00",
+ "read packet: $c#00",
+ "send packet: $OK#00",
+ {"direction": "send", "regex": "%Stop:T.*"},
+ # see the comment in TestNonStop.py, test_stdio
+ "read packet: $vStdio#00",
+ "read packet: $vStdio#00",
+ "send packet: $OK#00",
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+ self.assertIn("PID: {}".format(int(parent_pid, 16)).encode(),
+ ret["O_content"])
+ self.assertIn("PID: {}".format(int(child_pid, 16)).encode(),
+ ret["O_content"])
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -1113,14 +1113,16 @@
SendProcessOutput();
// Then stop the forwarding, so that any late output (see llvm.org/pr25652)
// does not interfere with our protocol.
- StopSTDIOForwarding();
+ if (!m_non_stop)
+ StopSTDIOForwarding();
HandleInferiorState_Stopped(process);
break;
case StateType::eStateExited:
// Same as above
SendProcessOutput();
- StopSTDIOForwarding();
+ if (!m_non_stop)
+ StopSTDIOForwarding();
HandleInferiorState_Exited(process);
break;
@@ -1425,7 +1427,8 @@
GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
Log *log = GetLog(LLDBLog::Process);
- StopSTDIOForwarding();
+ if (!m_non_stop)
+ StopSTDIOForwarding();
if (m_debugged_processes.empty()) {
LLDB_LOG(log, "No debugged process found.");
@@ -1451,7 +1454,8 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_vKill(
StringExtractorGDBRemote &packet) {
- StopSTDIOForwarding();
+ if (!m_non_stop)
+ StopSTDIOForwarding();
packet.SetFilePos(6); // vKill;
uint32_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
@@ -3542,7 +3546,8 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
Log *log = GetLog(LLDBLog::Process);
- StopSTDIOForwarding();
+ if (!m_non_stop)
+ StopSTDIOForwarding();
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
@@ -3941,6 +3946,8 @@
assert(packet_str.startswith("QNonStop:"));
packet_str.consume_front("QNonStop:");
if (packet_str == "0") {
+ if (m_non_stop)
+ StopSTDIOForwarding();
bool any_running = false;
for (auto &process_it : m_debugged_processes) {
if (process_it.second.process_up->IsRunning()) {
@@ -3965,6 +3972,8 @@
if (any_running)
return PacketResult::Success;
} else if (packet_str == "1") {
+ if (!m_non_stop)
+ StartSTDIOForwarding();
m_non_stop = true;
} else
return SendErrorResponse(Status("Invalid QNonStop packet"));
@@ -4258,9 +4267,10 @@
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() {
- // TODO: how to handle forwarding in non-stop mode?
+ if (m_non_stop)
+ return SendOKResponse();
StartSTDIOForwarding();
- return m_non_stop ? SendOKResponse() : PacketResult::Success;
+ return PacketResult::Success;
}
void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse(
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits