xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
1061da546Spatrick //===-- ScriptInterpreterPythonImpl.h ---------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9*be691f3bSpatrick #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
10*be691f3bSpatrick #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
11*be691f3bSpatrick 
12061da546Spatrick #include "lldb/Host/Config.h"
13061da546Spatrick 
14061da546Spatrick #if LLDB_ENABLE_PYTHON
15061da546Spatrick 
16061da546Spatrick #include "lldb-python.h"
17061da546Spatrick 
18061da546Spatrick #include "PythonDataObjects.h"
19061da546Spatrick #include "ScriptInterpreterPython.h"
20061da546Spatrick 
21061da546Spatrick #include "lldb/Host/Terminal.h"
22061da546Spatrick #include "lldb/Utility/StreamString.h"
23061da546Spatrick 
24061da546Spatrick #include "llvm/ADT/STLExtras.h"
25061da546Spatrick #include "llvm/ADT/StringRef.h"
26061da546Spatrick 
27061da546Spatrick namespace lldb_private {
28061da546Spatrick class IOHandlerPythonInterpreter;
29061da546Spatrick class ScriptInterpreterPythonImpl : public ScriptInterpreterPython {
30061da546Spatrick public:
31061da546Spatrick   friend class IOHandlerPythonInterpreter;
32061da546Spatrick 
33061da546Spatrick   ScriptInterpreterPythonImpl(Debugger &debugger);
34061da546Spatrick 
35061da546Spatrick   ~ScriptInterpreterPythonImpl() override;
36061da546Spatrick 
37061da546Spatrick   bool Interrupt() override;
38061da546Spatrick 
39061da546Spatrick   bool ExecuteOneLine(
40061da546Spatrick       llvm::StringRef command, CommandReturnObject *result,
41061da546Spatrick       const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
42061da546Spatrick 
43061da546Spatrick   void ExecuteInterpreterLoop() override;
44061da546Spatrick 
45061da546Spatrick   bool ExecuteOneLineWithReturn(
46061da546Spatrick       llvm::StringRef in_string,
47061da546Spatrick       ScriptInterpreter::ScriptReturnType return_type, void *ret_value,
48061da546Spatrick       const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
49061da546Spatrick 
50061da546Spatrick   lldb_private::Status ExecuteMultipleLines(
51061da546Spatrick       const char *in_string,
52061da546Spatrick       const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
53061da546Spatrick 
54061da546Spatrick   Status
55061da546Spatrick   ExportFunctionDefinitionToInterpreter(StringList &function_def) override;
56061da546Spatrick 
57061da546Spatrick   bool GenerateTypeScriptFunction(StringList &input, std::string &output,
58061da546Spatrick                                   const void *name_token = nullptr) override;
59061da546Spatrick 
60061da546Spatrick   bool GenerateTypeSynthClass(StringList &input, std::string &output,
61061da546Spatrick                               const void *name_token = nullptr) override;
62061da546Spatrick 
63061da546Spatrick   bool GenerateTypeSynthClass(const char *oneliner, std::string &output,
64061da546Spatrick                               const void *name_token = nullptr) override;
65061da546Spatrick 
66061da546Spatrick   // use this if the function code is just a one-liner script
67061da546Spatrick   bool GenerateTypeScriptFunction(const char *oneliner, std::string &output,
68061da546Spatrick                                   const void *name_token = nullptr) override;
69061da546Spatrick 
70061da546Spatrick   bool GenerateScriptAliasFunction(StringList &input,
71061da546Spatrick                                    std::string &output) override;
72061da546Spatrick 
73061da546Spatrick   StructuredData::ObjectSP
74061da546Spatrick   CreateSyntheticScriptedProvider(const char *class_name,
75061da546Spatrick                                   lldb::ValueObjectSP valobj) override;
76061da546Spatrick 
77061da546Spatrick   StructuredData::GenericSP
78061da546Spatrick   CreateScriptCommandObject(const char *class_name) override;
79061da546Spatrick 
80061da546Spatrick   StructuredData::ObjectSP
81061da546Spatrick   CreateScriptedThreadPlan(const char *class_name,
82061da546Spatrick                            StructuredDataImpl *args_data,
83061da546Spatrick                            std::string &error_str,
84061da546Spatrick                            lldb::ThreadPlanSP thread_plan) override;
85061da546Spatrick 
86061da546Spatrick   bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp,
87061da546Spatrick                                       Event *event,
88061da546Spatrick                                       bool &script_error) override;
89061da546Spatrick 
90061da546Spatrick   bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp,
91061da546Spatrick                                     Event *event, bool &script_error) override;
92061da546Spatrick 
93061da546Spatrick   bool ScriptedThreadPlanIsStale(StructuredData::ObjectSP implementor_sp,
94061da546Spatrick                                  bool &script_error) override;
95061da546Spatrick 
96061da546Spatrick   lldb::StateType
97061da546Spatrick   ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
98061da546Spatrick                                 bool &script_error) override;
99061da546Spatrick 
100061da546Spatrick   StructuredData::GenericSP
101061da546Spatrick   CreateScriptedBreakpointResolver(const char *class_name,
102061da546Spatrick                                    StructuredDataImpl *args_data,
103061da546Spatrick                                    lldb::BreakpointSP &bkpt_sp) override;
104061da546Spatrick   bool ScriptedBreakpointResolverSearchCallback(
105061da546Spatrick       StructuredData::GenericSP implementor_sp,
106061da546Spatrick       SymbolContext *sym_ctx) override;
107061da546Spatrick 
108061da546Spatrick   lldb::SearchDepth ScriptedBreakpointResolverSearchDepth(
109061da546Spatrick       StructuredData::GenericSP implementor_sp) override;
110061da546Spatrick 
111061da546Spatrick   StructuredData::GenericSP
112*be691f3bSpatrick   CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
113*be691f3bSpatrick                          StructuredDataImpl *args_data, Status &error) override;
114*be691f3bSpatrick 
115*be691f3bSpatrick   bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
116*be691f3bSpatrick                                   ExecutionContext &exc_ctx,
117*be691f3bSpatrick                                   lldb::StreamSP stream_sp) override;
118*be691f3bSpatrick 
119*be691f3bSpatrick   StructuredData::GenericSP
120061da546Spatrick   CreateFrameRecognizer(const char *class_name) override;
121061da546Spatrick 
122061da546Spatrick   lldb::ValueObjectListSP
123061da546Spatrick   GetRecognizedArguments(const StructuredData::ObjectSP &implementor,
124061da546Spatrick                          lldb::StackFrameSP frame_sp) override;
125061da546Spatrick 
126061da546Spatrick   StructuredData::GenericSP
127061da546Spatrick   OSPlugin_CreatePluginObject(const char *class_name,
128061da546Spatrick                               lldb::ProcessSP process_sp) override;
129061da546Spatrick 
130061da546Spatrick   StructuredData::DictionarySP
131061da546Spatrick   OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
132061da546Spatrick 
133061da546Spatrick   StructuredData::ArraySP
134061da546Spatrick   OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
135061da546Spatrick 
136061da546Spatrick   StructuredData::StringSP
137061da546Spatrick   OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
138061da546Spatrick                                lldb::tid_t thread_id) override;
139061da546Spatrick 
140061da546Spatrick   StructuredData::DictionarySP
141061da546Spatrick   OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
142061da546Spatrick                         lldb::tid_t tid, lldb::addr_t context) override;
143061da546Spatrick 
144061da546Spatrick   StructuredData::ObjectSP
145061da546Spatrick   LoadPluginModule(const FileSpec &file_spec,
146061da546Spatrick                    lldb_private::Status &error) override;
147061da546Spatrick 
148061da546Spatrick   StructuredData::DictionarySP
149061da546Spatrick   GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
150061da546Spatrick                      const char *setting_name,
151061da546Spatrick                      lldb_private::Status &error) override;
152061da546Spatrick 
153061da546Spatrick   size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,
154061da546Spatrick                               uint32_t max) override;
155061da546Spatrick 
156061da546Spatrick   lldb::ValueObjectSP
157061da546Spatrick   GetChildAtIndex(const StructuredData::ObjectSP &implementor,
158061da546Spatrick                   uint32_t idx) override;
159061da546Spatrick 
160061da546Spatrick   int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
161061da546Spatrick                               const char *child_name) override;
162061da546Spatrick 
163061da546Spatrick   bool UpdateSynthProviderInstance(
164061da546Spatrick       const StructuredData::ObjectSP &implementor) override;
165061da546Spatrick 
166061da546Spatrick   bool MightHaveChildrenSynthProviderInstance(
167061da546Spatrick       const StructuredData::ObjectSP &implementor) override;
168061da546Spatrick 
169061da546Spatrick   lldb::ValueObjectSP
170061da546Spatrick   GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
171061da546Spatrick 
172061da546Spatrick   ConstString
173061da546Spatrick   GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
174061da546Spatrick 
175061da546Spatrick   bool
176061da546Spatrick   RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
177061da546Spatrick                         ScriptedCommandSynchronicity synchronicity,
178061da546Spatrick                         lldb_private::CommandReturnObject &cmd_retobj,
179061da546Spatrick                         Status &error,
180061da546Spatrick                         const lldb_private::ExecutionContext &exe_ctx) override;
181061da546Spatrick 
182061da546Spatrick   bool RunScriptBasedCommand(
183061da546Spatrick       StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
184061da546Spatrick       ScriptedCommandSynchronicity synchronicity,
185061da546Spatrick       lldb_private::CommandReturnObject &cmd_retobj, Status &error,
186061da546Spatrick       const lldb_private::ExecutionContext &exe_ctx) override;
187061da546Spatrick 
188061da546Spatrick   Status GenerateFunction(const char *signature,
189061da546Spatrick                           const StringList &input) override;
190061da546Spatrick 
191061da546Spatrick   Status GenerateBreakpointCommandCallbackData(
192061da546Spatrick       StringList &input,
193061da546Spatrick       std::string &output,
194061da546Spatrick       bool has_extra_args) override;
195061da546Spatrick 
196061da546Spatrick   bool GenerateWatchpointCommandCallbackData(StringList &input,
197061da546Spatrick                                              std::string &output) override;
198061da546Spatrick 
199061da546Spatrick   bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
200061da546Spatrick                           StructuredData::ObjectSP &callee_wrapper_sp,
201061da546Spatrick                           const TypeSummaryOptions &options,
202061da546Spatrick                           std::string &retval) override;
203061da546Spatrick 
204061da546Spatrick   bool GetDocumentationForItem(const char *item, std::string &dest) override;
205061da546Spatrick 
206061da546Spatrick   bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
207061da546Spatrick                                     std::string &dest) override;
208061da546Spatrick 
209061da546Spatrick   uint32_t
210061da546Spatrick   GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
211061da546Spatrick 
212061da546Spatrick   bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
213061da546Spatrick                                    std::string &dest) override;
214061da546Spatrick 
215061da546Spatrick   bool CheckObjectExists(const char *name) override {
216061da546Spatrick     if (!name || !name[0])
217061da546Spatrick       return false;
218061da546Spatrick     std::string temp;
219061da546Spatrick     return GetDocumentationForItem(name, temp);
220061da546Spatrick   }
221061da546Spatrick 
222061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, Process *process,
223061da546Spatrick                               std::string &output, Status &error) override;
224061da546Spatrick 
225061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
226061da546Spatrick                               std::string &output, Status &error) override;
227061da546Spatrick 
228061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, Target *target,
229061da546Spatrick                               std::string &output, Status &error) override;
230061da546Spatrick 
231061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
232061da546Spatrick                               std::string &output, Status &error) override;
233061da546Spatrick 
234061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
235061da546Spatrick                               std::string &output, Status &error) override;
236061da546Spatrick 
237*be691f3bSpatrick   bool LoadScriptingModule(const char *filename,
238*be691f3bSpatrick                            const LoadScriptOptions &options,
239061da546Spatrick                            lldb_private::Status &error,
240*be691f3bSpatrick                            StructuredData::ObjectSP *module_sp = nullptr,
241*be691f3bSpatrick                            FileSpec extra_search_dir = {}) override;
242061da546Spatrick 
243061da546Spatrick   bool IsReservedWord(const char *word) override;
244061da546Spatrick 
245061da546Spatrick   std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
246061da546Spatrick 
247061da546Spatrick   void CollectDataForBreakpointCommandCallback(
248*be691f3bSpatrick       std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
249061da546Spatrick       CommandReturnObject &result) override;
250061da546Spatrick 
251061da546Spatrick   void
252061da546Spatrick   CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
253061da546Spatrick                                           CommandReturnObject &result) override;
254061da546Spatrick 
255061da546Spatrick   /// Set the callback body text into the callback for the breakpoint.
256*be691f3bSpatrick   Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
257061da546Spatrick                                       const char *callback_body) override;
258061da546Spatrick 
259061da546Spatrick   Status SetBreakpointCommandCallbackFunction(
260*be691f3bSpatrick       BreakpointOptions &bp_options, const char *function_name,
261061da546Spatrick       StructuredData::ObjectSP extra_args_sp) override;
262061da546Spatrick 
263061da546Spatrick   /// This one is for deserialization:
264061da546Spatrick   Status SetBreakpointCommandCallback(
265*be691f3bSpatrick       BreakpointOptions &bp_options,
266061da546Spatrick       std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
267061da546Spatrick 
268*be691f3bSpatrick   Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
269061da546Spatrick                                       const char *command_body_text,
270061da546Spatrick                                       StructuredData::ObjectSP extra_args_sp,
271061da546Spatrick                                       bool uses_extra_args);
272061da546Spatrick 
273061da546Spatrick   /// Set a one-liner as the callback for the watchpoint.
274061da546Spatrick   void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
275061da546Spatrick                                     const char *oneliner) override;
276061da546Spatrick 
277061da546Spatrick   const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
278061da546Spatrick 
279061da546Spatrick   PyThreadState *GetThreadState() { return m_command_thread_state; }
280061da546Spatrick 
281061da546Spatrick   void SetThreadState(PyThreadState *s) {
282061da546Spatrick     if (s)
283061da546Spatrick       m_command_thread_state = s;
284061da546Spatrick   }
285061da546Spatrick 
286061da546Spatrick   // IOHandlerDelegate
287061da546Spatrick   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;
288061da546Spatrick 
289061da546Spatrick   void IOHandlerInputComplete(IOHandler &io_handler,
290061da546Spatrick                               std::string &data) override;
291061da546Spatrick 
292061da546Spatrick   static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);
293061da546Spatrick 
294061da546Spatrick   // PluginInterface protocol
295061da546Spatrick   lldb_private::ConstString GetPluginName() override;
296061da546Spatrick 
297061da546Spatrick   uint32_t GetPluginVersion() override;
298061da546Spatrick 
299061da546Spatrick   class Locker : public ScriptInterpreterLocker {
300061da546Spatrick   public:
301061da546Spatrick     enum OnEntry {
302061da546Spatrick       AcquireLock = 0x0001,
303061da546Spatrick       InitSession = 0x0002,
304061da546Spatrick       InitGlobals = 0x0004,
305061da546Spatrick       NoSTDIN = 0x0008
306061da546Spatrick     };
307061da546Spatrick 
308061da546Spatrick     enum OnLeave {
309061da546Spatrick       FreeLock = 0x0001,
310061da546Spatrick       FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
311061da546Spatrick                                  // when calling constructor
312061da546Spatrick       TearDownSession = 0x0004
313061da546Spatrick     };
314061da546Spatrick 
315061da546Spatrick     Locker(ScriptInterpreterPythonImpl *py_interpreter,
316061da546Spatrick            uint16_t on_entry = AcquireLock | InitSession,
317061da546Spatrick            uint16_t on_leave = FreeLock | TearDownSession,
318061da546Spatrick            lldb::FileSP in = nullptr, lldb::FileSP out = nullptr,
319061da546Spatrick            lldb::FileSP err = nullptr);
320061da546Spatrick 
321061da546Spatrick     ~Locker() override;
322061da546Spatrick 
323061da546Spatrick   private:
324061da546Spatrick     bool DoAcquireLock();
325061da546Spatrick 
326061da546Spatrick     bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,
327061da546Spatrick                        lldb::FileSP out, lldb::FileSP err);
328061da546Spatrick 
329061da546Spatrick     bool DoFreeLock();
330061da546Spatrick 
331061da546Spatrick     bool DoTearDownSession();
332061da546Spatrick 
333061da546Spatrick     bool m_teardown_session;
334061da546Spatrick     ScriptInterpreterPythonImpl *m_python_interpreter;
335061da546Spatrick     PyGILState_STATE m_GILState;
336061da546Spatrick   };
337061da546Spatrick 
338061da546Spatrick   static bool BreakpointCallbackFunction(void *baton,
339061da546Spatrick                                          StoppointCallbackContext *context,
340061da546Spatrick                                          lldb::user_id_t break_id,
341061da546Spatrick                                          lldb::user_id_t break_loc_id);
342061da546Spatrick   static bool WatchpointCallbackFunction(void *baton,
343061da546Spatrick                                          StoppointCallbackContext *context,
344061da546Spatrick                                          lldb::user_id_t watch_id);
345061da546Spatrick   static void InitializePrivate();
346061da546Spatrick 
347061da546Spatrick   class SynchronicityHandler {
348061da546Spatrick   private:
349061da546Spatrick     lldb::DebuggerSP m_debugger_sp;
350061da546Spatrick     ScriptedCommandSynchronicity m_synch_wanted;
351061da546Spatrick     bool m_old_asynch;
352061da546Spatrick 
353061da546Spatrick   public:
354061da546Spatrick     SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);
355061da546Spatrick 
356061da546Spatrick     ~SynchronicityHandler();
357061da546Spatrick   };
358061da546Spatrick 
359061da546Spatrick   enum class AddLocation { Beginning, End };
360061da546Spatrick 
361061da546Spatrick   static void AddToSysPath(AddLocation location, std::string path);
362061da546Spatrick 
363061da546Spatrick   bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,
364061da546Spatrick                     lldb::FileSP err);
365061da546Spatrick 
366061da546Spatrick   void LeaveSession();
367061da546Spatrick 
368061da546Spatrick   uint32_t IsExecutingPython() const { return m_lock_count > 0; }
369061da546Spatrick 
370061da546Spatrick   uint32_t IncrementLockCount() { return ++m_lock_count; }
371061da546Spatrick 
372061da546Spatrick   uint32_t DecrementLockCount() {
373061da546Spatrick     if (m_lock_count > 0)
374061da546Spatrick       --m_lock_count;
375061da546Spatrick     return m_lock_count;
376061da546Spatrick   }
377061da546Spatrick 
378061da546Spatrick   enum ActiveIOHandler {
379061da546Spatrick     eIOHandlerNone,
380061da546Spatrick     eIOHandlerBreakpoint,
381061da546Spatrick     eIOHandlerWatchpoint
382061da546Spatrick   };
383061da546Spatrick 
384061da546Spatrick   python::PythonModule &GetMainModule();
385061da546Spatrick 
386061da546Spatrick   python::PythonDictionary &GetSessionDictionary();
387061da546Spatrick 
388061da546Spatrick   python::PythonDictionary &GetSysModuleDictionary();
389061da546Spatrick 
390061da546Spatrick   llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
391061da546Spatrick       const llvm::StringRef &callable_name) override;
392061da546Spatrick 
393061da546Spatrick   bool GetEmbeddedInterpreterModuleObjects();
394061da546Spatrick 
395061da546Spatrick   bool SetStdHandle(lldb::FileSP file, const char *py_name,
396061da546Spatrick                     python::PythonObject &save_file, const char *mode);
397061da546Spatrick 
398061da546Spatrick   python::PythonObject m_saved_stdin;
399061da546Spatrick   python::PythonObject m_saved_stdout;
400061da546Spatrick   python::PythonObject m_saved_stderr;
401061da546Spatrick   python::PythonModule m_main_module;
402061da546Spatrick   python::PythonDictionary m_session_dict;
403061da546Spatrick   python::PythonDictionary m_sys_module_dict;
404061da546Spatrick   python::PythonObject m_run_one_line_function;
405061da546Spatrick   python::PythonObject m_run_one_line_str_global;
406061da546Spatrick   std::string m_dictionary_name;
407061da546Spatrick   ActiveIOHandler m_active_io_handler;
408061da546Spatrick   bool m_session_is_active;
409dda28197Spatrick   bool m_pty_secondary_is_open;
410061da546Spatrick   bool m_valid_session;
411061da546Spatrick   uint32_t m_lock_count;
412061da546Spatrick   PyThreadState *m_command_thread_state;
413061da546Spatrick };
414061da546Spatrick 
415061da546Spatrick class IOHandlerPythonInterpreter : public IOHandler {
416061da546Spatrick public:
417061da546Spatrick   IOHandlerPythonInterpreter(Debugger &debugger,
418061da546Spatrick                              ScriptInterpreterPythonImpl *python)
419061da546Spatrick       : IOHandler(debugger, IOHandler::Type::PythonInterpreter),
420061da546Spatrick         m_python(python) {}
421061da546Spatrick 
422*be691f3bSpatrick   ~IOHandlerPythonInterpreter() override = default;
423061da546Spatrick 
424061da546Spatrick   ConstString GetControlSequence(char ch) override {
425061da546Spatrick     if (ch == 'd')
426061da546Spatrick       return ConstString("quit()\n");
427061da546Spatrick     return ConstString();
428061da546Spatrick   }
429061da546Spatrick 
430061da546Spatrick   void Run() override {
431061da546Spatrick     if (m_python) {
432061da546Spatrick       int stdin_fd = GetInputFD();
433061da546Spatrick       if (stdin_fd >= 0) {
434061da546Spatrick         Terminal terminal(stdin_fd);
435061da546Spatrick         TerminalState terminal_state;
436061da546Spatrick         const bool is_a_tty = terminal.IsATerminal();
437061da546Spatrick 
438061da546Spatrick         if (is_a_tty) {
439061da546Spatrick           terminal_state.Save(stdin_fd, false);
440061da546Spatrick           terminal.SetCanonical(false);
441061da546Spatrick           terminal.SetEcho(true);
442061da546Spatrick         }
443061da546Spatrick 
444061da546Spatrick         ScriptInterpreterPythonImpl::Locker locker(
445061da546Spatrick             m_python,
446061da546Spatrick             ScriptInterpreterPythonImpl::Locker::AcquireLock |
447061da546Spatrick                 ScriptInterpreterPythonImpl::Locker::InitSession |
448061da546Spatrick                 ScriptInterpreterPythonImpl::Locker::InitGlobals,
449061da546Spatrick             ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock |
450061da546Spatrick                 ScriptInterpreterPythonImpl::Locker::TearDownSession);
451061da546Spatrick 
452061da546Spatrick         // The following call drops into the embedded interpreter loop and
453061da546Spatrick         // stays there until the user chooses to exit from the Python
454061da546Spatrick         // interpreter. This embedded interpreter will, as any Python code that
455061da546Spatrick         // performs I/O, unlock the GIL before a system call that can hang, and
456061da546Spatrick         // lock it when the syscall has returned.
457061da546Spatrick 
458061da546Spatrick         // We need to surround the call to the embedded interpreter with calls
459061da546Spatrick         // to PyGILState_Ensure and PyGILState_Release (using the Locker
460061da546Spatrick         // above). This is because Python has a global lock which must be held
461061da546Spatrick         // whenever we want to touch any Python objects. Otherwise, if the user
462061da546Spatrick         // calls Python code, the interpreter state will be off, and things
463061da546Spatrick         // could hang (it's happened before).
464061da546Spatrick 
465061da546Spatrick         StreamString run_string;
466061da546Spatrick         run_string.Printf("run_python_interpreter (%s)",
467061da546Spatrick                           m_python->GetDictionaryName());
468061da546Spatrick         PyRun_SimpleString(run_string.GetData());
469061da546Spatrick 
470061da546Spatrick         if (is_a_tty)
471061da546Spatrick           terminal_state.Restore();
472061da546Spatrick       }
473061da546Spatrick     }
474061da546Spatrick     SetIsDone(true);
475061da546Spatrick   }
476061da546Spatrick 
477061da546Spatrick   void Cancel() override {}
478061da546Spatrick 
479061da546Spatrick   bool Interrupt() override { return m_python->Interrupt(); }
480061da546Spatrick 
481061da546Spatrick   void GotEOF() override {}
482061da546Spatrick 
483061da546Spatrick protected:
484061da546Spatrick   ScriptInterpreterPythonImpl *m_python;
485061da546Spatrick };
486061da546Spatrick 
487061da546Spatrick } // namespace lldb_private
488061da546Spatrick 
489*be691f3bSpatrick #endif // LLDB_ENABLE_PYTHON
490*be691f3bSpatrick #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
491