xref: /llvm-project/lldb/test/API/functionalities/process_group/TestChangeProcessGroup.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
199451b44SJordan Rupprecht"""Test that we handle inferiors which change their process group"""
299451b44SJordan Rupprecht
399451b44SJordan Rupprecht
499451b44SJordan Rupprechtimport os
599451b44SJordan Rupprechtimport lldb
699451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
799451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
899451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
999451b44SJordan Rupprecht
1099451b44SJordan Rupprecht
1199451b44SJordan Rupprechtclass ChangeProcessGroupTestCase(TestBase):
1299451b44SJordan Rupprecht    NO_DEBUG_INFO_TESTCASE = True
1399451b44SJordan Rupprecht
1499451b44SJordan Rupprecht    def setUp(self):
1599451b44SJordan Rupprecht        # Call super's setUp().
1699451b44SJordan Rupprecht        TestBase.setUp(self)
1799451b44SJordan Rupprecht        # Find the line number to break for main.c.
182238dcc3SJonas Devlieghere        self.line = line_number("main.c", "// Set breakpoint here")
1999451b44SJordan Rupprecht
2099451b44SJordan Rupprecht    @skipIfFreeBSD  # Times out on FreeBSD llvm.org/pr23731
2199451b44SJordan Rupprecht    @skipIfWindows  # setpgid call does not exist on Windows
2299451b44SJordan Rupprecht    @expectedFailureAndroid("http://llvm.org/pr23762", api_levels=[16])
2399451b44SJordan Rupprecht    @expectedFailureNetBSD
24239f488fSRaphael Isemann    @skipIftvOS  # fork not available on tvOS.
25239f488fSRaphael Isemann    @skipIfwatchOS  # fork not available on watchOS.
2699451b44SJordan Rupprecht    def test_setpgid(self):
2799451b44SJordan Rupprecht        self.build()
2899451b44SJordan Rupprecht        exe = self.getBuildArtifact("a.out")
2999451b44SJordan Rupprecht
3099451b44SJordan Rupprecht        # Use a file as a synchronization point between test and inferior.
312238dcc3SJonas Devlieghere        pid_file_path = lldbutil.append_to_process_working_directory(
322238dcc3SJonas Devlieghere            self, "pid_file_%d" % (int(time.time()))
332238dcc3SJonas Devlieghere        )
3499451b44SJordan Rupprecht        self.addTearDownHook(
352238dcc3SJonas Devlieghere            lambda: self.run_platform_command("rm %s" % (pid_file_path))
362238dcc3SJonas Devlieghere        )
3799451b44SJordan Rupprecht
3899451b44SJordan Rupprecht        popen = self.spawnSubprocess(exe, [pid_file_path])
3999451b44SJordan Rupprecht
4099451b44SJordan Rupprecht        pid = lldbutil.wait_for_file_on_target(self, pid_file_path)
4199451b44SJordan Rupprecht
4299451b44SJordan Rupprecht        # make sure we cleanup the forked child also
4399451b44SJordan Rupprecht        def cleanupChild():
4499451b44SJordan Rupprecht            if lldb.remote_platform:
4599451b44SJordan Rupprecht                lldb.remote_platform.Kill(int(pid))
4699451b44SJordan Rupprecht            else:
4799451b44SJordan Rupprecht                if os.path.exists("/proc/" + pid):
4899451b44SJordan Rupprecht                    os.kill(int(pid), signal.SIGKILL)
492238dcc3SJonas Devlieghere
5099451b44SJordan Rupprecht        self.addTearDownHook(cleanupChild)
5199451b44SJordan Rupprecht
5299451b44SJordan Rupprecht        # Create a target by the debugger.
5399451b44SJordan Rupprecht        target = self.dbg.CreateTarget(exe)
5499451b44SJordan Rupprecht        self.assertTrue(target, VALID_TARGET)
5599451b44SJordan Rupprecht
5699451b44SJordan Rupprecht        listener = lldb.SBListener("my.attach.listener")
5799451b44SJordan Rupprecht        error = lldb.SBError()
5899451b44SJordan Rupprecht        process = target.AttachToProcessWithID(listener, int(pid), error)
5999451b44SJordan Rupprecht        self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
6099451b44SJordan Rupprecht
6199451b44SJordan Rupprecht        # set a breakpoint just before the setpgid() call
6299451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
632238dcc3SJonas Devlieghere            self, "main.c", self.line, num_expected_locations=-1
642238dcc3SJonas Devlieghere        )
6599451b44SJordan Rupprecht
6699451b44SJordan Rupprecht        thread = process.GetSelectedThread()
6799451b44SJordan Rupprecht
6899451b44SJordan Rupprecht        # release the child from its loop
6999451b44SJordan Rupprecht        value = thread.GetSelectedFrame().EvaluateExpression("release_child_flag = 1")
70b3a0c4d7SRaphael Isemann        self.assertTrue(value.IsValid())
71*80fcecb1SJonas Devlieghere        self.assertEqual(value.GetValueAsUnsigned(0), 1)
7299451b44SJordan Rupprecht        process.Continue()
7399451b44SJordan Rupprecht
7499451b44SJordan Rupprecht        # make sure the child's process group id is different from its pid
7599451b44SJordan Rupprecht        value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)")
7699451b44SJordan Rupprecht        self.assertTrue(value.IsValid())
7799451b44SJordan Rupprecht        self.assertNotEqual(value.GetValueAsUnsigned(0), int(pid))
7899451b44SJordan Rupprecht
7999451b44SJordan Rupprecht        # step over the setpgid() call
8099451b44SJordan Rupprecht        thread.StepOver()
810f821339SJonas Devlieghere        self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonPlanComplete)
8299451b44SJordan Rupprecht
8399451b44SJordan Rupprecht        # verify that the process group has been set correctly
8499451b44SJordan Rupprecht        # this also checks that we are still in full control of the child
8599451b44SJordan Rupprecht        value = thread.GetSelectedFrame().EvaluateExpression("(int)getpgid(0)")
8699451b44SJordan Rupprecht        self.assertTrue(value.IsValid())
8799451b44SJordan Rupprecht        self.assertEqual(value.GetValueAsUnsigned(0), int(pid))
8899451b44SJordan Rupprecht
8999451b44SJordan Rupprecht        # run to completion
9099451b44SJordan Rupprecht        process.Continue()
911b8c7352SJonas Devlieghere        self.assertState(process.GetState(), lldb.eStateExited)
92