mgorny updated this revision to Diff 441664.
mgorny added a comment.
Fix `sem_destroy()` assertions.
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
@@ -10,8 +10,10 @@
#include <mutex>
#if !defined(_WIN32)
#include <pthread.h>
+#include <semaphore.h>
#include <signal.h>
#include <unistd.h>
+#include <sys/mman.h>
#endif
#include "thread.h"
#include <setjmp.h>
@@ -26,6 +28,13 @@
#include <TargetConditionals.h>
#endif
+#if !defined(_WIN32)
+struct semaphores {
+ sem_t parent_ready;
+ sem_t child_ready;
+};
+#endif
+
static const char *const PRINT_PID_COMMAND = "print-pid";
static bool g_print_thread_ids = false;
@@ -224,6 +233,9 @@
int return_value = 0;
#if !defined(_WIN32)
+ semaphores *sem = nullptr;
+ bool is_child = false;
+
// Set the signal handler.
sig_t sig_result = signal(SIGALRM, signal_handler);
if (sig_result == SIG_ERR) {
@@ -324,10 +336,29 @@
func_p();
#if !defined(_WIN32) && !defined(TARGET_OS_WATCH) && !defined(TARGET_OS_TV)
} else if (arg == "fork") {
- assert (fork() != -1);
+ // Prepare the semaphores for parent-child synchronization.
+ if (sem == nullptr) {
+ sem = static_cast<semaphores *>(mmap(nullptr, sizeof(*sem),
+ PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_SHARED, -1, 0));
+ assert(sem);
+ assert(sem_init(&sem->parent_ready, 1, 0) == 0);
+ assert(sem_init(&sem->child_ready, 1, 0) == 0);
+ }
+
+ 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 (arg == "process:sync") {
+ // this is only valid after fork
+ assert(sem);
+ sem_t *my_sem = is_child ? &sem->child_ready : &sem->parent_ready;
+ sem_t *other_sem = !is_child ? &sem->child_ready : &sem->parent_ready;
+ assert(sem_post(my_sem) == 0);
+ assert(sem_wait(other_sem) == 0);
#endif
} else if (consume_front(arg, "thread:new")) {
std::promise<void> promise;
@@ -368,5 +399,13 @@
it != threads.end(); ++it)
it->join();
+ if (sem != nullptr) {
+ if (!is_child) {
+ assert(sem_destroy(&sem->child_ready) == 0);
+ assert(sem_destroy(&sem->parent_ready) == 0);
+ }
+ assert(munmap(sem, sizeof(*sem)) == 0);
+ }
+
return return_value;
}
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 *
@@ -107,3 +109,31 @@
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):
+ parent_pid, parent_tid, child_pid, child_tid = (
+ self.start_fork_test(["fork", "process:sync", "print-pid",
+ "process:sync", "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
@@ -1107,14 +1107,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;
@@ -1417,7 +1419,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.");
@@ -1443,7 +1446,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);
@@ -3519,7 +3523,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;
@@ -3918,6 +3923,8 @@
assert(packet_str.startswith("QNonStop:"));
packet_str.consume_front("QNonStop:");
if (packet_str == "0") {
+ if (m_non_stop)
+ StopSTDIOForwarding();
for (const auto &process_it : m_debugged_processes) {
if (process_it.second->IsRunning()) {
Status error = process_it.second->Interrupt();
@@ -3935,6 +3942,8 @@
m_stop_notification_queue.clear();
m_non_stop = false;
} else if (packet_str == "1") {
+ if (!m_non_stop)
+ StartSTDIOForwarding();
m_non_stop = true;
} else
return SendErrorResponse(Status("Invalid QNonStop packet"));
@@ -4228,9 +4237,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