mgorny created this revision.
mgorny added reviewers: labath, emaste, krytarowski, jingham.
Herald added a subscriber: arichardson.
Herald added a project: All.
mgorny requested review of this revision.
Sponsored by: The FreeBSD Foundation
https://reviews.llvm.org/D128638
Files:
lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
Index: lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
===================================================================
--- lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
+++ lldb/test/API/tools/lldb-server/TestGdbRemoteFork.py
@@ -9,10 +9,12 @@
fork_regex = ("[$]T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
"{}:p([0-9a-f]+)[.]([0-9a-f]+).*")
+ fork_regex_nonstop = ("%Stop:T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
+ "{}:p([0-9a-f]+)[.]([0-9a-f]+).*")
fork_capture = {1: "parent_pid", 2: "parent_tid",
3: "child_pid", 4: "child_tid"}
- def start_fork_test(self, args, variant="fork"):
+ def start_fork_test(self, args, variant="fork", nonstop=False):
self.build()
self.prep_debug_monitor_and_inferior(inferior_args=args)
self.add_qSupported_packets(["multiprocess+",
@@ -22,11 +24,24 @@
self.reset_test_sequence()
# continue and expect fork
- self.test_sequence.add_log_lines([
- "read packet: $c#00",
- {"direction": "send", "regex": self.fork_regex.format(variant),
- "capture": self.fork_capture},
- ], True)
+ if nonstop:
+ self.test_sequence.add_log_lines([
+ "read packet: $QNonStop:1#00",
+ "send packet: $OK#00",
+ "read packet: $c#00",
+ "send packet: $OK#00",
+ {"direction": "send",
+ "regex": self.fork_regex_nonstop.format(variant),
+ "capture": self.fork_capture},
+ "read packet: $vStopped#00",
+ "send packet: $OK#00",
+ ], True)
+ else:
+ self.test_sequence.add_log_lines([
+ "read packet: $c#00",
+ {"direction": "send", "regex": self.fork_regex.format(variant),
+ "capture": self.fork_capture},
+ ], True)
ret = self.expect_gdbremote_sequence()
self.reset_test_sequence()
@@ -45,9 +60,9 @@
], True)
self.expect_gdbremote_sequence()
- def fork_and_detach_test(self, variant):
+ def fork_and_detach_test(self, variant, nonstop=False):
parent_pid, parent_tid, child_pid, child_tid = (
- self.start_fork_test([variant], variant))
+ self.start_fork_test([variant], variant, nonstop=nonstop))
# detach the forked child
self.test_sequence.add_log_lines([
@@ -77,6 +92,20 @@
], True)
self.expect_gdbremote_sequence()
+ @add_test_categories(["fork"])
+ def test_fork_nonstop(self):
+ parent_pid, _ = self.fork_and_detach_test("fork", nonstop=True)
+
+ # resume the parent
+ self.test_sequence.add_log_lines([
+ "read packet: $c#00",
+ "send packet: $OK#00",
+ "send packet: %Stop:W00;process:{}#00".format(parent_pid),
+ "read packet: $vStopped#00",
+ "send packet: $OK#00",
+ ], True)
+ self.expect_gdbremote_sequence()
+
@add_test_categories(["fork"])
def test_vfork(self):
parent_pid, parent_tid = self.fork_and_detach_test("vfork")
@@ -93,9 +122,32 @@
], True)
self.expect_gdbremote_sequence()
- def fork_and_follow_test(self, variant):
+ @add_test_categories(["fork"])
+ def test_vfork_nonstop(self):
+ parent_pid, parent_tid = self.fork_and_detach_test("vfork",
+ nonstop=True)
+
+ # resume the parent
+ self.test_sequence.add_log_lines([
+ "read packet: $c#00",
+ "send packet: $OK#00",
+ {"direction": "send",
+ "regex": r"%Stop:T05thread:p{}[.]{}.*vforkdone.*".format(
+ parent_pid, parent_tid),
+ },
+ "read packet: $vStopped#00",
+ "send packet: $OK#00",
+ "read packet: $c#00",
+ "send packet: $OK#00",
+ "send packet: %Stop:W00;process:{}#00".format(parent_pid),
+ "read packet: $vStopped#00",
+ "send packet: $OK#00",
+ ], True)
+ self.expect_gdbremote_sequence()
+
+ def fork_and_follow_test(self, variant, nonstop=False):
parent_pid, parent_tid, child_pid, child_tid = (
- self.start_fork_test([variant], variant))
+ self.start_fork_test([variant], variant, nonstop=nonstop))
# switch to the forked child
self.test_sequence.add_log_lines([
@@ -113,18 +165,37 @@
"send packet: $OK#00",
# then resume the child
"read packet: $c#00",
- "send packet: $W00;process:{}#00".format(child_pid),
], True)
+
+ if nonstop:
+ self.test_sequence.add_log_lines([
+ "send packet: $OK#00",
+ "send packet: %Stop:W00;process:{}#00".format(child_pid),
+ "read packet: $vStopped#00",
+ "send packet: $OK#00",
+ ], True)
+ else:
+ self.test_sequence.add_log_lines([
+ "send packet: $W00;process:{}#00".format(child_pid),
+ ], True)
self.expect_gdbremote_sequence()
@add_test_categories(["fork"])
def test_fork_follow(self):
self.fork_and_follow_test("fork")
+ @add_test_categories(["fork"])
+ def test_fork_follow_nonstop(self):
+ self.fork_and_follow_test("fork", nonstop=True)
+
@add_test_categories(["fork"])
def test_vfork_follow(self):
self.fork_and_follow_test("vfork")
+ @add_test_categories(["fork"])
+ def test_vfork_follow_nonstop(self):
+ self.fork_and_follow_test("vfork", nonstop=True)
+
@add_test_categories(["fork"])
def test_select_wrong_pid(self):
self.build()
@@ -191,10 +262,9 @@
], True)
self.expect_gdbremote_sequence()
- @add_test_categories(["fork"])
- def test_detach_all(self):
+ def detach_all_test(self, nonstop=False):
parent_pid, parent_tid, child_pid, child_tid = (
- self.start_fork_test(["fork"]))
+ self.start_fork_test(["fork"], nonstop=nonstop))
self.test_sequence.add_log_lines([
# double-check our PIDs
@@ -213,6 +283,14 @@
], True)
self.expect_gdbremote_sequence()
+ @add_test_categories(["fork"])
+ def test_detach_all(self):
+ self.detach_all_test()
+
+ @add_test_categories(["fork"])
+ def test_detach_all_nonstop(self):
+ self.detach_all_test(nonstop=True)
+
@add_test_categories(["fork"])
def test_kill_all(self):
parent_pid, _, child_pid, _ = self.start_fork_test(["fork"])
@@ -230,10 +308,51 @@
self.assertEqual(set([ret["pid1"], ret["pid2"]]),
set([parent_pid, child_pid]))
- def vkill_test(self, kill_parent=False, kill_child=False):
+ @add_test_categories(["fork"])
+ def test_kill_all_nonstop(self):
+ parent_pid, _, child_pid, _ = self.start_fork_test(["fork"],
+ nonstop=True)
+
+ exit_regex = "X09;process:([0-9a-f]+)"
+ # Depending on a potential race, the second kill may make it into
+ # the async queue before we issue vStopped or after. In the former
+ # case, we should expect the exit status in reply to vStopped.
+ # In the latter, we should expect an OK response (queue empty),
+ # followed by another async notification.
+ vstop_regex = "[$](OK|{})#.*".format(exit_regex)
+ self.test_sequence.add_log_lines([
+ # kill all processes
+ "read packet: $k#00",
+ "send packet: $OK#00",
+ {"direction": "send", "regex": "%Stop:{}#.*".format(exit_regex),
+ "capture": {1: "pid1"}},
+ "read packet: $vStopped#00",
+ {"direction": "send", "regex": vstop_regex,
+ "capture": {1: "vstop_reply", 2: "pid2"}},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+ pid1 = ret["pid1"]
+ if ret["vstop_reply"] == "OK":
+ self.reset_test_sequence()
+ self.test_sequence.add_log_lines([
+ {"direction": "send", "regex": "%Stop:{}#.*".format(exit_regex),
+ "capture": {1: "pid2"}},
+ ], True)
+ ret = self.expect_gdbremote_sequence()
+ pid2 = ret["pid2"]
+ self.reset_test_sequence()
+ self.test_sequence.add_log_lines([
+ "read packet: $vStopped#00",
+ "send packet: $OK#00",
+ ], True)
+ self.expect_gdbremote_sequence()
+ self.assertEqual(set([ret["pid1"], ret["pid2"]]),
+ set([parent_pid, child_pid]))
+
+ def vkill_test(self, kill_parent=False, kill_child=False, nonstop=False):
assert kill_parent or kill_child
parent_pid, parent_tid, child_pid, child_tid = (
- self.start_fork_test(["fork"]))
+ self.start_fork_test(["fork"], nonstop=nonstop))
if kill_parent:
self.test_sequence.add_log_lines([
@@ -269,6 +388,10 @@
def test_vkill_both(self):
self.vkill_test(kill_parent=True, kill_child=True)
+ @add_test_categories(["fork"])
+ def test_vkill_both_nonstop(self):
+ self.vkill_test(kill_parent=True, kill_child=True, nonstop=True)
+
def resume_one_test(self, run_order, use_vCont=False):
parent_pid, parent_tid, child_pid, child_tid = (
self.start_fork_test(["fork", "trap"]))
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits