reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
"""Test that we handle inferiors that send signals to themselves"""

from __future__ import print_function


import lldb
import re
from lldbsuite.test.lldbplatformutil import getDarwinOSTriples
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


@skipIfWindows  # signals do not exist on Windows
class RaiseTestCase(TestBase):

    mydir = TestBase.compute_mydir(__file__)
    NO_DEBUG_INFO_TESTCASE = True

    @skipIfNetBSD  # Hangs on NetBSD
    def test_sigstop(self):
        self.build()
        self.signal_test('SIGSTOP', False)
        # passing of SIGSTOP is not correctly handled, so not testing that
        # scenario: https://llvm.org/bugs/show_bug.cgi?id=23574

    @skipIfDarwin  # darwin does not support real time signals
    @skipIfTargetAndroid()
    def test_sigsigrtmin(self):
        self.build()
        self.signal_test('SIGRTMIN', True)

    @skipIfNetBSD  # Hangs on NetBSD
    def test_sigtrap(self):
        self.build()
        self.signal_test('SIGTRAP', True)

    def launch(self, target, signal):
        # launch the process, do not stop at entry point.
        process = target.LaunchSimple(
            [signal], None, self.get_process_working_directory())
        self.assertTrue(process, PROCESS_IS_VALID)
        self.assertEqual(process.GetState(), lldb.eStateStopped)
        thread = lldbutil.get_stopped_thread(
            process, lldb.eStopReasonBreakpoint)
        self.assertTrue(
            thread.IsValid(),
            "Thread should be stopped due to a breakpoint")
        return process

    def set_handle(self, signal, pass_signal, stop_at_signal, notify_signal):
        return_obj = lldb.SBCommandReturnObject()
        self.dbg.GetCommandInterpreter().HandleCommand(
            "process handle %s -p %s -s %s -n %s" %
            (signal, pass_signal, stop_at_signal, notify_signal), return_obj)
        self.assertTrue(
            return_obj.Succeeded(),
            "Setting signal handling failed")

    def signal_test(self, signal, test_passing):
        """Test that we handle inferior raising signals"""
        exe = self.getBuildArtifact("a.out")

        # Create a target by the debugger.
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)
        lldbutil.run_break_set_by_symbol(self, "main")

        # launch
        process = self.launch(target, signal)
        signo = process.GetUnixSignals().GetSignalNumberFromName(signal)

        # retrieve default signal disposition
        return_obj = lldb.SBCommandReturnObject()
        self.dbg.GetCommandInterpreter().HandleCommand(
            "process handle %s " % signal, return_obj)
        match = re.match(
            'NAME *PASS *STOP *NOTIFY.*(false|true) *(false|true) *(false|true)',
            return_obj.GetOutput(),
            re.IGNORECASE | re.DOTALL)
        if not match:
            self.fail('Unable to retrieve default signal disposition.')
        default_pass = match.group(1)
        default_stop = match.group(2)
        default_notify = match.group(3)

        # Make sure we stop at the signal
        self.set_handle(signal, "false", "true", "true")
        process.Continue()
        self.assertEqual(process.GetState(), lldb.eStateStopped)
        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal)
        self.assertTrue(
            thread.IsValid(),
            "Thread should be stopped due to a signal")
        self.assertTrue(
            thread.GetStopReasonDataCount() >= 1,
            "There was data in the event.")
        self.assertEqual(thread.GetStopReasonDataAtIndex(0), signo,
                         "The stop signal was %s" % signal)

        # Continue until we exit.
        process.Continue()
        self.assertEqual(process.GetState(), lldb.eStateExited)
        self.assertEqual(process.GetExitStatus(), 0)

        # launch again
        process = self.launch(target, signal)

        # Make sure we do not stop at the signal. We should still get the
        # notification.
        self.set_handle(signal, "false", "false", "true")
        self.expect(
            "process continue",
            substrs=[
                "stopped and restarted",
                signal])
        self.assertEqual(process.GetState(), lldb.eStateExited)
        self.assertEqual(process.GetExitStatus(), 0)

        # launch again
        process = self.launch(target, signal)

        # Make sure we do not stop at the signal, and we do not get the
        # notification.
        self.set_handle(signal, "false", "false", "false")
        self.expect(
            "process continue",
            substrs=["stopped and restarted"],
            matching=False)
        self.assertEqual(process.GetState(), lldb.eStateExited)
        self.assertEqual(process.GetExitStatus(), 0)

        if not test_passing:
            # reset signal handling to default
            self.set_handle(signal, default_pass, default_stop, default_notify)
            return

        # launch again
        process = self.launch(target, signal)

        # Make sure we stop at the signal
        self.set_handle(signal, "true", "true", "true")
        process.Continue()
        self.assertEqual(process.GetState(), lldb.eStateStopped)
        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal)
        self.assertTrue(
            thread.IsValid(),
            "Thread should be stopped due to a signal")
        self.assertTrue(
            thread.GetStopReasonDataCount() >= 1,
            "There was data in the event.")
        self.assertEqual(
            thread.GetStopReasonDataAtIndex(0),
            process.GetUnixSignals().GetSignalNumberFromName(signal),
            "The stop signal was %s" %
            signal)

        # Continue until we exit. The process should receive the signal.
        process.Continue()
        self.assertEqual(process.GetState(), lldb.eStateExited)
        self.assertEqual(process.GetExitStatus(), signo)

        # launch again
        process = self.launch(target, signal)

        # Make sure we do not stop at the signal. We should still get the notification. Process
        # should receive the signal.
        self.set_handle(signal, "true", "false", "true")
        self.expect(
            "process continue",
            substrs=[
                "stopped and restarted",
                signal])
        self.assertEqual(process.GetState(), lldb.eStateExited)
        self.assertEqual(process.GetExitStatus(), signo)

        # launch again
        process = self.launch(target, signal)

        # Make sure we do not stop at the signal, and we do not get the notification. Process
        # should receive the signal.
        self.set_handle(signal, "true", "false", "false")
        self.expect(
            "process continue",
            substrs=["stopped and restarted"],
            matching=False)
        self.assertEqual(process.GetState(), lldb.eStateExited)
        self.assertEqual(process.GetExitStatus(), signo)

        # reset signal handling to default
        self.set_handle(signal, default_pass, default_stop, default_notify)