xref: /llvm-project/lldb/test/API/python_api/was_interrupted/interruptible.py (revision 586114510c5fa71d1377c7f53e68a3b12c472aa2)
1fe61b382SJim Inghamimport lldb
2fe61b382SJim Inghamimport threading
3fe61b382SJim Ingham
4fe61b382SJim Inghamlocal_data = None
5fe61b382SJim Ingham
62238dcc3SJonas Devlieghere
7fe61b382SJim Inghamclass BarrierContainer(threading.local):
8fe61b382SJim Ingham    def __init__(self, before_interrupt_barrier, after_interrupt_barrier, event):
9fe61b382SJim Ingham        self.event = event
10fe61b382SJim Ingham        self.before_interrupt_barrier = before_interrupt_barrier
11fe61b382SJim Ingham        self.after_interrupt_barrier = after_interrupt_barrier
12fe61b382SJim Ingham
13fe61b382SJim Ingham
142238dcc3SJonas Devlieghereclass WelcomeCommand(object):
15fe61b382SJim Ingham    def __init__(self, debugger, session_dict):
16fe61b382SJim Ingham        return
17fe61b382SJim Ingham
18fe61b382SJim Ingham    def get_short_help(self):
19fe61b382SJim Ingham        return "A command that waits for an interrupt before returning."
20fe61b382SJim Ingham
21fe61b382SJim Ingham    def check_was_interrupted(self, debugger, use_interpreter):
22fe61b382SJim Ingham        if use_interpreter:
23fe61b382SJim Ingham            self.was_interrupted = debugger.GetCommandInterpreter().WasInterrupted()
24fe61b382SJim Ingham        else:
25fe61b382SJim Ingham            self.was_interrupted = debugger.InterruptRequested()
26fe61b382SJim Ingham        if local_data.event:
27fe61b382SJim Ingham            self.was_canceled = local_data.event.is_set()
28fe61b382SJim Ingham
29fe61b382SJim Ingham    def __call__(self, debugger, args, exe_ctx, result):
30fe61b382SJim Ingham        """Command arguments:
31fe61b382SJim Ingham        {interp/debugger} - Whether to use SBCommandInterpreter::WasInterrupted
32fe61b382SJim Ingham                            of SBDebugger::InterruptRequested().
33fe61b382SJim Ingham        check - Don't do the rendevous, just check if an interrupt was requested.
34fe61b382SJim Ingham                If check is not provided, we'll do the lock and then check.
35fe61b382SJim Ingham        poll  - Should we poll once after the rendevous or spin waiting for the
36fe61b382SJim Ingham                interruption to happen.
37fe61b382SJim Ingham
38fe61b382SJim Ingham        For the interrupt cases, the command waits serially on the barriers
39fe61b382SJim Ingham        passed to it in local data, giving the test runner a chance to set the
40fe61b382SJim Ingham        interrupt.  Once the barriers are passed, it waits for the interrupt
41fe61b382SJim Ingham        or the event.
42fe61b382SJim Ingham        If it finds an interrupt, it returns "Command was interrupted". If it gets an
43fe61b382SJim Ingham        event before seeing the interrupt it returns "Command was not interrupted."
44fe61b382SJim Ingham        For the "poll" case, it waits on the rendevous, then checks once.
45fe61b382SJim Ingham        For the "check" case, it doesn't wait, but just returns whether there was
46fe61b382SJim Ingham        an interrupt in force or not."""
47fe61b382SJim Ingham
48*58611451SEisuke Kawashima        if local_data is None:
49fe61b382SJim Ingham            result.SetError("local data was not set.")
50fe61b382SJim Ingham            result.SetStatus(lldb.eReturnStatusFailed)
51fe61b382SJim Ingham            return
52fe61b382SJim Ingham
53fe61b382SJim Ingham        use_interpreter = "interp" in args
54fe61b382SJim Ingham        if not use_interpreter:
55fe61b382SJim Ingham            if not "debugger" in args:
56fe61b382SJim Ingham                result.SetError("Must pass either 'interp' or 'debugger'")
57fe61b382SJim Ingham                result.SetStatus(lldb.eReturnStatusFailed)
58fe61b382SJim Ingham                return
59fe61b382SJim Ingham
60fe61b382SJim Ingham        self.was_interrupted = False
61fe61b382SJim Ingham        self.was_canceled = False
62fe61b382SJim Ingham
63fe61b382SJim Ingham        if "check" in args:
64fe61b382SJim Ingham            self.check_was_interrupted(debugger, use_interpreter)
65fe61b382SJim Ingham            if self.was_interrupted:
66fe61b382SJim Ingham                result.Print("Command was interrupted")
67fe61b382SJim Ingham            else:
68fe61b382SJim Ingham                result.Print("Command was not interrupted")
69fe61b382SJim Ingham        else:
70fe61b382SJim Ingham            # Wait here to rendevous in the test before it sets the interrupt.
71fe61b382SJim Ingham            local_data.before_interrupt_barrier.wait()
72fe61b382SJim Ingham            # Now the test will set the interrupt, and we can continue:
73fe61b382SJim Ingham            local_data.after_interrupt_barrier.wait()
74fe61b382SJim Ingham
75fe61b382SJim Ingham            if "poll" in args:
76fe61b382SJim Ingham                self.check_was_interrupted(debugger, use_interpreter)
77fe61b382SJim Ingham            else:
78fe61b382SJim Ingham                while not self.was_interrupted and not self.was_canceled:
79fe61b382SJim Ingham                    self.check_was_interrupted(debugger, use_interpreter)
80fe61b382SJim Ingham
81fe61b382SJim Ingham            if self.was_interrupted:
82fe61b382SJim Ingham                result.Print("Command was interrupted")
83fe61b382SJim Ingham            else:
84fe61b382SJim Ingham                result.Print("Command was not interrupted")
85fe61b382SJim Ingham
86fe61b382SJim Ingham            if self.was_canceled:
87fe61b382SJim Ingham                result.Print("Command was canceled")
88fe61b382SJim Ingham        result.SetStatus(lldb.eReturnStatusSuccessFinishResult)
89fe61b382SJim Ingham        return True
90