labath updated this revision to Diff 412643.
labath marked 3 inline comments as done.
labath added a comment.

Address mgorny's comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D120320/new/

https://reviews.llvm.org/D120320

Files:
  lldb/packages/Python/lldbsuite/test/lldbpexpect.py
  lldb/test/API/driver/job_control/TestJobControl.py
  lldb/test/API/driver/job_control/shell.py
  lldb/tools/driver/Driver.cpp

Index: lldb/tools/driver/Driver.cpp
===================================================================
--- lldb/tools/driver/Driver.cpp
+++ lldb/tools/driver/Driver.cpp
@@ -671,23 +671,30 @@
   _exit(signo);
 }
 
-void sigtstp_handler(int signo) {
+#ifndef _WIN32
+static void sigtstp_handler(int signo) {
   if (g_driver != nullptr)
     g_driver->GetDebugger().SaveInputTerminalState();
 
+  // Unblock the signal and remove our handler.
+  sigset_t set;
+  sigemptyset(&set);
+  sigaddset(&set, signo);
+  pthread_sigmask(SIG_UNBLOCK, &set, nullptr);
   signal(signo, SIG_DFL);
-  kill(getpid(), signo);
+
+  // Now re-raise the signal. We will immediately suspend...
+  raise(signo);
+  // ... and resume after a SIGCONT.
+
+  // Now undo the modifications.
+  pthread_sigmask(SIG_BLOCK, &set, nullptr);
   signal(signo, sigtstp_handler);
-}
 
-void sigcont_handler(int signo) {
   if (g_driver != nullptr)
     g_driver->GetDebugger().RestoreInputTerminalState();
-
-  signal(signo, SIG_DFL);
-  kill(getpid(), signo);
-  signal(signo, sigcont_handler);
 }
+#endif
 
 void reproducer_handler(void *finalize_cmd) {
   if (SBReproducer::Generate()) {
@@ -834,7 +841,6 @@
   signal(SIGPIPE, SIG_IGN);
   signal(SIGWINCH, sigwinch_handler);
   signal(SIGTSTP, sigtstp_handler);
-  signal(SIGCONT, sigcont_handler);
 #endif
 
   int exit_code = 0;
Index: lldb/test/API/driver/job_control/shell.py
===================================================================
--- /dev/null
+++ lldb/test/API/driver/job_control/shell.py
@@ -0,0 +1,34 @@
+"""
+Launch a process (given through argv) similar to how a shell would do it.
+"""
+
+import signal
+import subprocess
+import sys
+import os
+
+
+def preexec_fn():
+    # Block SIGTTOU generated by the tcsetpgrp call
+    orig_mask = signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGTTOU])
+
+    # Put us in a new process group.
+    os.setpgid(0, 0)
+
+    # And put it in the foreground.
+    fd = os.open("/dev/tty", os.O_RDONLY)
+    os.tcsetpgrp(fd, os.getpgid(0))
+    os.close(fd)
+
+    signal.pthread_sigmask(signal.SIG_SETMASK, orig_mask)
+
+
+if __name__ == "__main__":
+    child = subprocess.Popen(sys.argv[1:], preexec_fn=preexec_fn)
+    print("PID=%d" % child.pid)
+
+    _, status = os.waitpid(child.pid, os.WUNTRACED)
+    print("STATUS=%d" % status)
+
+    returncode = child.wait()
+    print("RETURNCODE=%d" % returncode)
Index: lldb/test/API/driver/job_control/TestJobControl.py
===================================================================
--- /dev/null
+++ lldb/test/API/driver/job_control/TestJobControl.py
@@ -0,0 +1,32 @@
+"""
+Test lldb's handling of job control signals (SIGTSTP, SIGCONT).
+"""
+
+
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.lldbpexpect import PExpectTest
+
+
+class JobControlTest(PExpectTest):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def test_job_control(self):
+        def post_spawn():
+            self.child.expect("PID=([0-9]+)")
+            self.lldb_pid = int(self.child.match[1])
+
+        run_under = [sys.executable, self.getSourcePath('shell.py')]
+        self.launch(run_under=run_under, post_spawn=post_spawn)
+
+        os.kill(self.lldb_pid, signal.SIGTSTP)
+        self.child.expect("STATUS=([0-9]+)")
+        status = int(self.child.match[1])
+
+        self.assertTrue(os.WIFSTOPPED(status))
+        self.assertEquals(os.WSTOPSIG(status), signal.SIGTSTP)
+
+        os.kill(self.lldb_pid, signal.SIGCONT)
+
+        self.child.sendline("quit")
+        self.child.expect("RETURNCODE=0")
Index: lldb/packages/Python/lldbsuite/test/lldbpexpect.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/lldbpexpect.py
+++ lldb/packages/Python/lldbsuite/test/lldbpexpect.py
@@ -23,11 +23,15 @@
     def expect_prompt(self):
         self.child.expect_exact(self.PROMPT)
 
-    def launch(self, executable=None, extra_args=None, timeout=60, dimensions=None):
+    def launch(self, executable=None, extra_args=None, timeout=60,
+               dimensions=None, run_under=None, post_spawn=None):
         logfile = getattr(sys.stdout, 'buffer',
                             sys.stdout) if self.TraceOn() else None
 
-        args = ['--no-lldbinit', '--no-use-colors']
+        args = []
+        if run_under is not None:
+            args += run_under
+        args += [lldbtest_config.lldbExec, '--no-lldbinit', '--no-use-colors']
         for cmd in self.setUpCommands():
             args += ['-O', cmd]
         if executable is not None:
@@ -41,8 +45,11 @@
 
         import pexpect
         self.child = pexpect.spawn(
-                lldbtest_config.lldbExec, args=args, logfile=logfile,
+                args[0], args=args[1:], logfile=logfile,
                 timeout=timeout, dimensions=dimensions, env=env)
+
+        if post_spawn is not None:
+            post_spawn()
         self.expect_prompt()
         for cmd in self.setUpCommands():
             self.child.expect_exact(cmd)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to