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 
9be691f3bSpatrick #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
10be691f3bSpatrick #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
11be691f3bSpatrick 
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,
82*f6aab3d8Srobert                            const 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,
102*f6aab3d8Srobert                                    const 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
112be691f3bSpatrick   CreateScriptedStopHook(lldb::TargetSP target_sp, const char *class_name,
113*f6aab3d8Srobert                          const StructuredDataImpl &args_data,
114*f6aab3d8Srobert                          Status &error) override;
115be691f3bSpatrick 
116be691f3bSpatrick   bool ScriptedStopHookHandleStop(StructuredData::GenericSP implementor_sp,
117be691f3bSpatrick                                   ExecutionContext &exc_ctx,
118be691f3bSpatrick                                   lldb::StreamSP stream_sp) override;
119be691f3bSpatrick 
120be691f3bSpatrick   StructuredData::GenericSP
121061da546Spatrick   CreateFrameRecognizer(const char *class_name) override;
122061da546Spatrick 
123061da546Spatrick   lldb::ValueObjectListSP
124061da546Spatrick   GetRecognizedArguments(const StructuredData::ObjectSP &implementor,
125061da546Spatrick                          lldb::StackFrameSP frame_sp) override;
126061da546Spatrick 
127061da546Spatrick   StructuredData::GenericSP
128061da546Spatrick   OSPlugin_CreatePluginObject(const char *class_name,
129061da546Spatrick                               lldb::ProcessSP process_sp) override;
130061da546Spatrick 
131061da546Spatrick   StructuredData::DictionarySP
132061da546Spatrick   OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
133061da546Spatrick 
134061da546Spatrick   StructuredData::ArraySP
135061da546Spatrick   OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
136061da546Spatrick 
137061da546Spatrick   StructuredData::StringSP
138061da546Spatrick   OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp,
139061da546Spatrick                                lldb::tid_t thread_id) override;
140061da546Spatrick 
141061da546Spatrick   StructuredData::DictionarySP
142061da546Spatrick   OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp,
143061da546Spatrick                         lldb::tid_t tid, lldb::addr_t context) override;
144061da546Spatrick 
145061da546Spatrick   StructuredData::ObjectSP
146061da546Spatrick   LoadPluginModule(const FileSpec &file_spec,
147061da546Spatrick                    lldb_private::Status &error) override;
148061da546Spatrick 
149061da546Spatrick   StructuredData::DictionarySP
150061da546Spatrick   GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target,
151061da546Spatrick                      const char *setting_name,
152061da546Spatrick                      lldb_private::Status &error) override;
153061da546Spatrick 
154061da546Spatrick   size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor,
155061da546Spatrick                               uint32_t max) override;
156061da546Spatrick 
157061da546Spatrick   lldb::ValueObjectSP
158061da546Spatrick   GetChildAtIndex(const StructuredData::ObjectSP &implementor,
159061da546Spatrick                   uint32_t idx) override;
160061da546Spatrick 
161061da546Spatrick   int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor,
162061da546Spatrick                               const char *child_name) override;
163061da546Spatrick 
164061da546Spatrick   bool UpdateSynthProviderInstance(
165061da546Spatrick       const StructuredData::ObjectSP &implementor) override;
166061da546Spatrick 
167061da546Spatrick   bool MightHaveChildrenSynthProviderInstance(
168061da546Spatrick       const StructuredData::ObjectSP &implementor) override;
169061da546Spatrick 
170061da546Spatrick   lldb::ValueObjectSP
171061da546Spatrick   GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
172061da546Spatrick 
173061da546Spatrick   ConstString
174061da546Spatrick   GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
175061da546Spatrick 
176061da546Spatrick   bool
177061da546Spatrick   RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
178061da546Spatrick                         ScriptedCommandSynchronicity synchronicity,
179061da546Spatrick                         lldb_private::CommandReturnObject &cmd_retobj,
180061da546Spatrick                         Status &error,
181061da546Spatrick                         const lldb_private::ExecutionContext &exe_ctx) override;
182061da546Spatrick 
183061da546Spatrick   bool RunScriptBasedCommand(
184061da546Spatrick       StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
185061da546Spatrick       ScriptedCommandSynchronicity synchronicity,
186061da546Spatrick       lldb_private::CommandReturnObject &cmd_retobj, Status &error,
187061da546Spatrick       const lldb_private::ExecutionContext &exe_ctx) override;
188061da546Spatrick 
189061da546Spatrick   Status GenerateFunction(const char *signature,
190061da546Spatrick                           const StringList &input) override;
191061da546Spatrick 
192061da546Spatrick   Status GenerateBreakpointCommandCallbackData(
193061da546Spatrick       StringList &input,
194061da546Spatrick       std::string &output,
195061da546Spatrick       bool has_extra_args) override;
196061da546Spatrick 
197061da546Spatrick   bool GenerateWatchpointCommandCallbackData(StringList &input,
198061da546Spatrick                                              std::string &output) override;
199061da546Spatrick 
200061da546Spatrick   bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj,
201061da546Spatrick                           StructuredData::ObjectSP &callee_wrapper_sp,
202061da546Spatrick                           const TypeSummaryOptions &options,
203061da546Spatrick                           std::string &retval) override;
204061da546Spatrick 
205*f6aab3d8Srobert   bool FormatterCallbackFunction(const char *function_name,
206*f6aab3d8Srobert                                  lldb::TypeImplSP type_impl_sp) override;
207*f6aab3d8Srobert 
208061da546Spatrick   bool GetDocumentationForItem(const char *item, std::string &dest) override;
209061da546Spatrick 
210061da546Spatrick   bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
211061da546Spatrick                                     std::string &dest) override;
212061da546Spatrick 
213061da546Spatrick   uint32_t
214061da546Spatrick   GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override;
215061da546Spatrick 
216061da546Spatrick   bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp,
217061da546Spatrick                                    std::string &dest) override;
218061da546Spatrick 
CheckObjectExists(const char * name)219061da546Spatrick   bool CheckObjectExists(const char *name) override {
220061da546Spatrick     if (!name || !name[0])
221061da546Spatrick       return false;
222061da546Spatrick     std::string temp;
223061da546Spatrick     return GetDocumentationForItem(name, temp);
224061da546Spatrick   }
225061da546Spatrick 
226061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, Process *process,
227061da546Spatrick                               std::string &output, Status &error) override;
228061da546Spatrick 
229061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, Thread *thread,
230061da546Spatrick                               std::string &output, Status &error) override;
231061da546Spatrick 
232061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, Target *target,
233061da546Spatrick                               std::string &output, Status &error) override;
234061da546Spatrick 
235061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, StackFrame *frame,
236061da546Spatrick                               std::string &output, Status &error) override;
237061da546Spatrick 
238061da546Spatrick   bool RunScriptFormatKeyword(const char *impl_function, ValueObject *value,
239061da546Spatrick                               std::string &output, Status &error) override;
240061da546Spatrick 
241be691f3bSpatrick   bool LoadScriptingModule(const char *filename,
242be691f3bSpatrick                            const LoadScriptOptions &options,
243061da546Spatrick                            lldb_private::Status &error,
244be691f3bSpatrick                            StructuredData::ObjectSP *module_sp = nullptr,
245be691f3bSpatrick                            FileSpec extra_search_dir = {}) override;
246061da546Spatrick 
247061da546Spatrick   bool IsReservedWord(const char *word) override;
248061da546Spatrick 
249061da546Spatrick   std::unique_ptr<ScriptInterpreterLocker> AcquireInterpreterLock() override;
250061da546Spatrick 
251061da546Spatrick   void CollectDataForBreakpointCommandCallback(
252be691f3bSpatrick       std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
253061da546Spatrick       CommandReturnObject &result) override;
254061da546Spatrick 
255061da546Spatrick   void
256061da546Spatrick   CollectDataForWatchpointCommandCallback(WatchpointOptions *wp_options,
257061da546Spatrick                                           CommandReturnObject &result) override;
258061da546Spatrick 
259061da546Spatrick   /// Set the callback body text into the callback for the breakpoint.
260be691f3bSpatrick   Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
261061da546Spatrick                                       const char *callback_body) override;
262061da546Spatrick 
263061da546Spatrick   Status SetBreakpointCommandCallbackFunction(
264be691f3bSpatrick       BreakpointOptions &bp_options, const char *function_name,
265061da546Spatrick       StructuredData::ObjectSP extra_args_sp) override;
266061da546Spatrick 
267061da546Spatrick   /// This one is for deserialization:
268061da546Spatrick   Status SetBreakpointCommandCallback(
269be691f3bSpatrick       BreakpointOptions &bp_options,
270061da546Spatrick       std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
271061da546Spatrick 
272be691f3bSpatrick   Status SetBreakpointCommandCallback(BreakpointOptions &bp_options,
273061da546Spatrick                                       const char *command_body_text,
274061da546Spatrick                                       StructuredData::ObjectSP extra_args_sp,
275061da546Spatrick                                       bool uses_extra_args);
276061da546Spatrick 
277061da546Spatrick   /// Set a one-liner as the callback for the watchpoint.
278061da546Spatrick   void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
279061da546Spatrick                                     const char *oneliner) override;
280061da546Spatrick 
GetDictionaryName()281061da546Spatrick   const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
282061da546Spatrick 
GetThreadState()283061da546Spatrick   PyThreadState *GetThreadState() { return m_command_thread_state; }
284061da546Spatrick 
SetThreadState(PyThreadState * s)285061da546Spatrick   void SetThreadState(PyThreadState *s) {
286061da546Spatrick     if (s)
287061da546Spatrick       m_command_thread_state = s;
288061da546Spatrick   }
289061da546Spatrick 
290061da546Spatrick   // IOHandlerDelegate
291061da546Spatrick   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override;
292061da546Spatrick 
293061da546Spatrick   void IOHandlerInputComplete(IOHandler &io_handler,
294061da546Spatrick                               std::string &data) override;
295061da546Spatrick 
296061da546Spatrick   static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);
297061da546Spatrick 
298061da546Spatrick   // PluginInterface protocol
GetPluginName()299*f6aab3d8Srobert   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
300061da546Spatrick 
301061da546Spatrick   class Locker : public ScriptInterpreterLocker {
302061da546Spatrick   public:
303061da546Spatrick     enum OnEntry {
304061da546Spatrick       AcquireLock = 0x0001,
305061da546Spatrick       InitSession = 0x0002,
306061da546Spatrick       InitGlobals = 0x0004,
307061da546Spatrick       NoSTDIN = 0x0008
308061da546Spatrick     };
309061da546Spatrick 
310061da546Spatrick     enum OnLeave {
311061da546Spatrick       FreeLock = 0x0001,
312061da546Spatrick       FreeAcquiredLock = 0x0002, // do not free the lock if we already held it
313061da546Spatrick                                  // when calling constructor
314061da546Spatrick       TearDownSession = 0x0004
315061da546Spatrick     };
316061da546Spatrick 
317061da546Spatrick     Locker(ScriptInterpreterPythonImpl *py_interpreter,
318061da546Spatrick            uint16_t on_entry = AcquireLock | InitSession,
319061da546Spatrick            uint16_t on_leave = FreeLock | TearDownSession,
320061da546Spatrick            lldb::FileSP in = nullptr, lldb::FileSP out = nullptr,
321061da546Spatrick            lldb::FileSP err = nullptr);
322061da546Spatrick 
323061da546Spatrick     ~Locker() override;
324061da546Spatrick 
325061da546Spatrick   private:
326061da546Spatrick     bool DoAcquireLock();
327061da546Spatrick 
328061da546Spatrick     bool DoInitSession(uint16_t on_entry_flags, lldb::FileSP in,
329061da546Spatrick                        lldb::FileSP out, lldb::FileSP err);
330061da546Spatrick 
331061da546Spatrick     bool DoFreeLock();
332061da546Spatrick 
333061da546Spatrick     bool DoTearDownSession();
334061da546Spatrick 
335061da546Spatrick     bool m_teardown_session;
336061da546Spatrick     ScriptInterpreterPythonImpl *m_python_interpreter;
337061da546Spatrick     PyGILState_STATE m_GILState;
338061da546Spatrick   };
339061da546Spatrick 
340061da546Spatrick   static bool BreakpointCallbackFunction(void *baton,
341061da546Spatrick                                          StoppointCallbackContext *context,
342061da546Spatrick                                          lldb::user_id_t break_id,
343061da546Spatrick                                          lldb::user_id_t break_loc_id);
344061da546Spatrick   static bool WatchpointCallbackFunction(void *baton,
345061da546Spatrick                                          StoppointCallbackContext *context,
346061da546Spatrick                                          lldb::user_id_t watch_id);
347*f6aab3d8Srobert   static void Initialize();
348061da546Spatrick 
349061da546Spatrick   class SynchronicityHandler {
350061da546Spatrick   private:
351061da546Spatrick     lldb::DebuggerSP m_debugger_sp;
352061da546Spatrick     ScriptedCommandSynchronicity m_synch_wanted;
353061da546Spatrick     bool m_old_asynch;
354061da546Spatrick 
355061da546Spatrick   public:
356061da546Spatrick     SynchronicityHandler(lldb::DebuggerSP, ScriptedCommandSynchronicity);
357061da546Spatrick 
358061da546Spatrick     ~SynchronicityHandler();
359061da546Spatrick   };
360061da546Spatrick 
361061da546Spatrick   enum class AddLocation { Beginning, End };
362061da546Spatrick 
363061da546Spatrick   static void AddToSysPath(AddLocation location, std::string path);
364061da546Spatrick 
365061da546Spatrick   bool EnterSession(uint16_t on_entry_flags, lldb::FileSP in, lldb::FileSP out,
366061da546Spatrick                     lldb::FileSP err);
367061da546Spatrick 
368061da546Spatrick   void LeaveSession();
369061da546Spatrick 
IsExecutingPython()370061da546Spatrick   uint32_t IsExecutingPython() const { return m_lock_count > 0; }
371061da546Spatrick 
IncrementLockCount()372061da546Spatrick   uint32_t IncrementLockCount() { return ++m_lock_count; }
373061da546Spatrick 
DecrementLockCount()374061da546Spatrick   uint32_t DecrementLockCount() {
375061da546Spatrick     if (m_lock_count > 0)
376061da546Spatrick       --m_lock_count;
377061da546Spatrick     return m_lock_count;
378061da546Spatrick   }
379061da546Spatrick 
380061da546Spatrick   enum ActiveIOHandler {
381061da546Spatrick     eIOHandlerNone,
382061da546Spatrick     eIOHandlerBreakpoint,
383061da546Spatrick     eIOHandlerWatchpoint
384061da546Spatrick   };
385061da546Spatrick 
386061da546Spatrick   python::PythonModule &GetMainModule();
387061da546Spatrick 
388061da546Spatrick   python::PythonDictionary &GetSessionDictionary();
389061da546Spatrick 
390061da546Spatrick   python::PythonDictionary &GetSysModuleDictionary();
391061da546Spatrick 
392061da546Spatrick   llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
393061da546Spatrick       const llvm::StringRef &callable_name) override;
394061da546Spatrick 
395061da546Spatrick   bool GetEmbeddedInterpreterModuleObjects();
396061da546Spatrick 
397061da546Spatrick   bool SetStdHandle(lldb::FileSP file, const char *py_name,
398061da546Spatrick                     python::PythonObject &save_file, const char *mode);
399061da546Spatrick 
400061da546Spatrick   python::PythonObject m_saved_stdin;
401061da546Spatrick   python::PythonObject m_saved_stdout;
402061da546Spatrick   python::PythonObject m_saved_stderr;
403061da546Spatrick   python::PythonModule m_main_module;
404061da546Spatrick   python::PythonDictionary m_session_dict;
405061da546Spatrick   python::PythonDictionary m_sys_module_dict;
406061da546Spatrick   python::PythonObject m_run_one_line_function;
407061da546Spatrick   python::PythonObject m_run_one_line_str_global;
408061da546Spatrick   std::string m_dictionary_name;
409061da546Spatrick   ActiveIOHandler m_active_io_handler;
410061da546Spatrick   bool m_session_is_active;
411dda28197Spatrick   bool m_pty_secondary_is_open;
412061da546Spatrick   bool m_valid_session;
413061da546Spatrick   uint32_t m_lock_count;
414061da546Spatrick   PyThreadState *m_command_thread_state;
415061da546Spatrick };
416061da546Spatrick 
417061da546Spatrick class IOHandlerPythonInterpreter : public IOHandler {
418061da546Spatrick public:
IOHandlerPythonInterpreter(Debugger & debugger,ScriptInterpreterPythonImpl * python)419061da546Spatrick   IOHandlerPythonInterpreter(Debugger &debugger,
420061da546Spatrick                              ScriptInterpreterPythonImpl *python)
421061da546Spatrick       : IOHandler(debugger, IOHandler::Type::PythonInterpreter),
422061da546Spatrick         m_python(python) {}
423061da546Spatrick 
424be691f3bSpatrick   ~IOHandlerPythonInterpreter() override = default;
425061da546Spatrick 
GetControlSequence(char ch)426061da546Spatrick   ConstString GetControlSequence(char ch) override {
427061da546Spatrick     if (ch == 'd')
428061da546Spatrick       return ConstString("quit()\n");
429061da546Spatrick     return ConstString();
430061da546Spatrick   }
431061da546Spatrick 
Run()432061da546Spatrick   void Run() override {
433061da546Spatrick     if (m_python) {
434061da546Spatrick       int stdin_fd = GetInputFD();
435061da546Spatrick       if (stdin_fd >= 0) {
436061da546Spatrick         Terminal terminal(stdin_fd);
437*f6aab3d8Srobert         TerminalState terminal_state(terminal);
438061da546Spatrick 
439*f6aab3d8Srobert         if (terminal.IsATerminal()) {
440*f6aab3d8Srobert           // FIXME: error handling?
441*f6aab3d8Srobert           llvm::consumeError(terminal.SetCanonical(false));
442*f6aab3d8Srobert           llvm::consumeError(terminal.SetEcho(true));
443061da546Spatrick         }
444061da546Spatrick 
445061da546Spatrick         ScriptInterpreterPythonImpl::Locker locker(
446061da546Spatrick             m_python,
447061da546Spatrick             ScriptInterpreterPythonImpl::Locker::AcquireLock |
448061da546Spatrick                 ScriptInterpreterPythonImpl::Locker::InitSession |
449061da546Spatrick                 ScriptInterpreterPythonImpl::Locker::InitGlobals,
450061da546Spatrick             ScriptInterpreterPythonImpl::Locker::FreeAcquiredLock |
451061da546Spatrick                 ScriptInterpreterPythonImpl::Locker::TearDownSession);
452061da546Spatrick 
453061da546Spatrick         // The following call drops into the embedded interpreter loop and
454061da546Spatrick         // stays there until the user chooses to exit from the Python
455061da546Spatrick         // interpreter. This embedded interpreter will, as any Python code that
456061da546Spatrick         // performs I/O, unlock the GIL before a system call that can hang, and
457061da546Spatrick         // lock it when the syscall has returned.
458061da546Spatrick 
459061da546Spatrick         // We need to surround the call to the embedded interpreter with calls
460061da546Spatrick         // to PyGILState_Ensure and PyGILState_Release (using the Locker
461061da546Spatrick         // above). This is because Python has a global lock which must be held
462061da546Spatrick         // whenever we want to touch any Python objects. Otherwise, if the user
463061da546Spatrick         // calls Python code, the interpreter state will be off, and things
464061da546Spatrick         // could hang (it's happened before).
465061da546Spatrick 
466061da546Spatrick         StreamString run_string;
467061da546Spatrick         run_string.Printf("run_python_interpreter (%s)",
468061da546Spatrick                           m_python->GetDictionaryName());
469061da546Spatrick         PyRun_SimpleString(run_string.GetData());
470061da546Spatrick       }
471061da546Spatrick     }
472061da546Spatrick     SetIsDone(true);
473061da546Spatrick   }
474061da546Spatrick 
Cancel()475061da546Spatrick   void Cancel() override {}
476061da546Spatrick 
Interrupt()477061da546Spatrick   bool Interrupt() override { return m_python->Interrupt(); }
478061da546Spatrick 
GotEOF()479061da546Spatrick   void GotEOF() override {}
480061da546Spatrick 
481061da546Spatrick protected:
482061da546Spatrick   ScriptInterpreterPythonImpl *m_python;
483061da546Spatrick };
484061da546Spatrick 
485061da546Spatrick } // namespace lldb_private
486061da546Spatrick 
487be691f3bSpatrick #endif // LLDB_ENABLE_PYTHON
488be691f3bSpatrick #endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHONIMPL_H
489