diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp | 378 |
1 files changed, 211 insertions, 167 deletions
diff --git a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp index c1d28e8..1b24fea 100644 --- a/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/contrib/llvm/tools/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -31,7 +31,8 @@ #include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" -#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/Pipe.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/PythonDataObjects.h" @@ -41,33 +42,26 @@ using namespace lldb; using namespace lldb_private; -static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL; -static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL; -static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = NULL; -static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL; -static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = NULL; -static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = NULL; -static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL; -static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL; -static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL; -static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = NULL; -static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL; -static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = NULL; -static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL; -static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL; -static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = NULL; -static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = NULL; -static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = NULL; -static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = NULL; -static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = NULL; -static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = NULL; - -static int -_check_and_flush (FILE *stream) -{ - int prev_fail = ferror (stream); - return fflush (stream) || prev_fail ? EOF : 0; -} +static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = nullptr; +static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr; +static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr; +static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr; +static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr; +static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr; +static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr; +static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr; +static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr; +static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; +static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; +static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; +static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = nullptr; +static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; +static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; +static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr; +static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; +static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; +static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; +static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; static std::string ReadPythonBacktrace (PyObject* py_backtrace); @@ -100,6 +94,13 @@ ScriptInterpreterPython::Locker::DoAcquireLock() m_GILState = PyGILState_Ensure(); if (log) log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); + + // we need to save the thread state when we first start the command + // because we might decide to interrupt it while some action is taking + // place outside of Python (e.g. printing to screen, waiting for the network, ...) + // in that case, _PyThreadState_Current will be NULL - and we would be unable + // to set the asynchronous exception - not a desirable situation + m_python_interpreter->SetThreadState (_PyThreadState_Current); return true; } @@ -156,7 +157,7 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete m_session_is_active (false), m_pty_slave_is_open (false), m_valid_session (true), - m_command_thread_state (NULL) + m_command_thread_state (nullptr) { ScriptInterpreterPython::InitializePrivate (); @@ -213,7 +214,7 @@ ScriptInterpreterPython::~ScriptInterpreterPython () void ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler) { - const char *instructions = NULL; + const char *instructions = nullptr; switch (m_active_io_handler) { @@ -255,24 +256,30 @@ ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::str break; case eIOHandlerBreakpoint: { - BreakpointOptions *bp_options = (BreakpointOptions *)io_handler.GetUserData(); - std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); - if (data_ap.get()) + std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); + for (auto bp_options : *bp_options_vec) { - data_ap->user_source.SplitIntoLines(data); - - if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) + if (!bp_options) + continue; + + std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); + if (data_ap.get()) { - BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); - bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); - } - else if (!batch_mode) - { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); - if (error_sp) + data_ap->user_source.SplitIntoLines(data); + + if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success()) { - error_sp->Printf ("Warning: No command attached to breakpoint.\n"); - error_sp->Flush(); + BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); + bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); + } + else if (!batch_mode) + { + StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + if (error_sp) + { + error_sp->Printf ("Warning: No command attached to breakpoint.\n"); + error_sp->Flush(); + } } } } @@ -306,8 +313,6 @@ ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::str } break; } - - } @@ -427,42 +432,42 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, lldb::StreamFileSP in_sp; lldb::StreamFileSP out_sp; lldb::StreamFileSP err_sp; - if (in == NULL || out == NULL || err == NULL) + if (in == nullptr || out == nullptr || err == nullptr) m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp); - if (in == NULL && in_sp && (on_entry_flags & Locker::NoSTDIN) == 0) + if (in == nullptr && in_sp && (on_entry_flags & Locker::NoSTDIN) == 0) in = in_sp->GetFile().GetStream(); if (in) { m_saved_stdin.Reset(sys_module_dict.GetItemForKey("stdin")); - PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", 0); + PyObject *new_file = PyFile_FromFile (in, (char *) "", (char *) "r", nullptr); sys_module_dict.SetItemForKey ("stdin", new_file); Py_DECREF (new_file); } else m_saved_stdin.Reset(); - if (out == NULL && out_sp) + if (out == nullptr && out_sp) out = out_sp->GetFile().GetStream(); if (out) { m_saved_stdout.Reset(sys_module_dict.GetItemForKey("stdout")); - PyObject *new_file = PyFile_FromFile (out, (char *) "", (char *) "w", 0); + PyObject *new_file = PyFile_FromFile (out, (char *) "", (char *) "w", nullptr); sys_module_dict.SetItemForKey ("stdout", new_file); Py_DECREF (new_file); } else m_saved_stdout.Reset(); - if (err == NULL && err_sp) + if (err == nullptr && err_sp) err = err_sp->GetFile().GetStream(); if (err) { m_saved_stderr.Reset(sys_module_dict.GetItemForKey("stderr")); - PyObject *new_file = PyFile_FromFile (err, (char *) "", (char *) "w", 0); + PyObject *new_file = PyFile_FromFile (err, (char *) "", (char *) "w", nullptr); sys_module_dict.SetItemForKey ("stderr", new_file); Py_DECREF (new_file); } @@ -517,7 +522,7 @@ ScriptInterpreterPython::GetSysModuleDictionary () static std::string GenerateUniqueName (const char* base_name_wanted, uint32_t& functions_counter, - void* name_token = NULL) + void* name_token = nullptr) { StreamString sstr; @@ -538,7 +543,7 @@ ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects () if (!m_run_one_line_function) { PyObject *module = PyImport_AddModule ("lldb.embedded_interpreter"); - if (module != NULL) + if (module != nullptr) { PythonDictionary module_dict (PyModule_GetDict (module)); if (module_dict) @@ -580,8 +585,7 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec StreamFileSP output_file_sp; StreamFileSP error_file_sp; Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm"); - int pipe_fds[2] = { -1, -1 }; - + bool join_read_thread = false; if (options.GetEnableIO()) { if (result) @@ -589,20 +593,21 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec input_file_sp = debugger.GetInputFile(); // Set output to a temporary file so we can forward the results on to the result object - int err = pipe(pipe_fds); - if (err == 0) + Pipe pipe; + if (pipe.Open()) { - std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe_fds[0], true)); + std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); if (conn_ap->IsConnected()) { output_comm.SetConnection(conn_ap.release()); output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream()); output_comm.StartReadThread(); - FILE *outfile_handle = fdopen (pipe_fds[1], "w"); + join_read_thread = true; + FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w"); output_file_sp.reset(new StreamFile(outfile_handle, true)); error_file_sp = output_file_sp; if (outfile_handle) - ::setbuf (outfile_handle, NULL); + ::setbuf (outfile_handle, nullptr); result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream()); result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream()); @@ -667,7 +672,7 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec if (out_file != err_file) ::fflush (err_file); - if (pipe_fds[0] != -1) + if (join_read_thread) { // Close the write end of the pipe since we are done with our // one line script. This should cause the read thread that @@ -788,10 +793,27 @@ public: } - virtual void + virtual bool Interrupt () { - + Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); + + PyThreadState* state = _PyThreadState_Current; + if (!state) + state = m_python->GetThreadState(); + if (state) + { + long tid = state->thread_id; + _PyThreadState_Current = state; + int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); + if (log) + log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p", + tid, num_threads, static_cast<void *>(state)); + } + else if (log) + log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL"); + + return false; } virtual void @@ -834,13 +856,13 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, { Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), + ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); - PyObject *py_return = NULL; + PyObject *py_return = nullptr; PythonObject &main_module = GetMainModule (); PythonDictionary globals (PyModule_GetDict(main_module.get())); - PyObject *py_error = NULL; + PyObject *py_error = nullptr; bool ret_success = false; int success; @@ -855,25 +877,25 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, locals = globals; py_error = PyErr_Occurred(); - if (py_error != NULL) + if (py_error != nullptr) PyErr_Clear(); - if (in_string != NULL) + if (in_string != nullptr) { { // scope for PythonInputReaderManager //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); py_return = PyRun_String (in_string, Py_eval_input, globals.get(), locals.get()); - if (py_return == NULL) + if (py_return == nullptr) { py_error = PyErr_Occurred (); - if (py_error != NULL) + if (py_error != nullptr) PyErr_Clear (); py_return = PyRun_String (in_string, Py_single_input, globals.get(), locals.get()); } } - if (py_return != NULL) + if (py_return != nullptr) { switch (return_type) { @@ -978,7 +1000,7 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, } py_error = PyErr_Occurred(); - if (py_error != NULL) + if (py_error != nullptr) { ret_success = false; if (options.GetMaskoutErrors()) @@ -998,14 +1020,13 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec Error error; Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), + ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); - bool success = false; PythonObject return_value; PythonObject &main_module = GetMainModule (); PythonDictionary globals (PyModule_GetDict(main_module.get())); - PyObject *py_error = NULL; + PyObject *py_error = nullptr; PythonDictionary locals = GetSessionDictionary (); @@ -1020,10 +1041,10 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec } py_error = PyErr_Occurred(); - if (py_error != NULL) + if (py_error != nullptr) PyErr_Clear(); - if (in_string != NULL) + if (in_string != nullptr) { struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input); if (compiled_node) @@ -1031,27 +1052,22 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py"); if (compiled_code) { - { // scope for PythonInputReaderManager - //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); - return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get())); - } - if (return_value) - success = true; + return_value.Reset(PyEval_EvalCode (compiled_code, globals.get(), locals.get())); } } } py_error = PyErr_Occurred (); - if (py_error != NULL) + if (py_error != nullptr) { // puts(in_string); // _PyObject_Dump (py_error); // PyErr_Print(); // success = false; - PyObject *type = NULL; - PyObject *value = NULL; - PyObject *traceback = NULL; + PyObject *type = nullptr; + PyObject *value = nullptr; + PyObject *traceback = nullptr; PyErr_Fetch (&type,&value,&traceback); // get the backtrace @@ -1075,11 +1091,11 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec void -ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, +ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, CommandReturnObject &result) { m_active_io_handler = eIOHandlerBreakpoint; - m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, bp_options); + m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, &bp_options_vec); } void @@ -1090,27 +1106,39 @@ ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOpti m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_options); } -// Set a Python one-liner as the callback for the breakpoint. void +ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, + const char *function_name) +{ + // For now just cons up a oneliner that calls the provided function. + std::string oneliner("return "); + oneliner += function_name; + oneliner += "(frame, bp_loc, internal_dict)"; + m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, + oneliner.c_str()); +} + +// Set a Python one-liner as the callback for the breakpoint. +Error ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options, - const char *oneliner) + const char *command_body_text) { std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); - // It's necessary to set both user_source and script_source to the oneliner. - // The former is used to generate callback description (as in breakpoint command list) - // while the latter is used for Python to interpret during the actual callback. - - data_ap->user_source.AppendString (oneliner); - data_ap->script_source.assign (oneliner); - - if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) + // Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData. That will + // wrap the body in an auto-generated function, and return the function name in script_source. That is what + // the callback will actually invoke. + + data_ap->user_source.SplitIntoLines(command_body_text); + Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source); + if (error.Success()) { BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); + return error; } - - return; + else + return error; } // Set a Python one-liner as the callback for the watchpoint. @@ -1136,24 +1164,32 @@ ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_opt return; } -bool +Error ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def) { // Convert StringList to one long, newline delimited, const char *. std::string function_def_string(function_def.CopyList()); - return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)).Success(); + Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); + return error; } -bool +Error ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input) { + Error error; int num_lines = input.GetSize (); if (num_lines == 0) - return false; + { + error.SetErrorString ("No input data."); + return error; + } if (!signature || *signature == 0) - return false; + { + error.SetErrorString("No output function name."); + return error; + } StreamString sstr; StringList auto_generated_function; @@ -1180,11 +1216,9 @@ ScriptInterpreterPython::GenerateFunction(const char *signature, const StringLis // Verify that the results are valid Python. - if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) - return false; + error = ExportFunctionDefinitionToInterpreter (auto_generated_function); - return true; - + return error; } bool @@ -1204,7 +1238,7 @@ ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token)); sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input)) + if (!GenerateFunction(sstr.GetData(), user_input).Success()) return false; // Store the name of the auto-generated function to be called. @@ -1227,7 +1261,7 @@ ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, st sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(),user_input)) + if (!GenerateFunction(sstr.GetData(),user_input).Success()) return false; // Store the name of the auto-generated function to be called. @@ -1273,7 +1307,7 @@ ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::st // Verify that the results are valid Python. // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported) // (TODO: rename that method to ExportDefinitionToInterpreter) - if (!ExportFunctionDefinitionToInterpreter (auto_generated_class)) + if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success()) return false; // Store the name of the auto-generated class @@ -1285,7 +1319,7 @@ ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::st lldb::ScriptInterpreterObjectSP ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp) { - if (class_name == NULL || class_name[0] == '\0') + if (class_name == nullptr || class_name[0] == '\0') return lldb::ScriptInterpreterObjectSP(); if (!process_sp) @@ -1319,7 +1353,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - if (implementor == NULL || implementor == Py_None) + if (implementor == nullptr || implementor == Py_None) return lldb::ScriptInterpreterObjectSP(); PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); @@ -1329,7 +1363,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP PyErr_Clear(); } - if (pmeth == NULL || pmeth == Py_None) + if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); return lldb::ScriptInterpreterObjectSP(); @@ -1354,7 +1388,7 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP Py_XDECREF(pmeth); // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL); + PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) @@ -1380,7 +1414,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - if (implementor == NULL || implementor == Py_None) + if (implementor == nullptr || implementor == Py_None) return lldb::ScriptInterpreterObjectSP(); PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); @@ -1390,7 +1424,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o PyErr_Clear(); } - if (pmeth == NULL || pmeth == Py_None) + if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); return lldb::ScriptInterpreterObjectSP(); @@ -1415,7 +1449,7 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP o Py_XDECREF(pmeth); // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL); + PyObject* py_return = PyObject_CallMethod(implementor, callee_name, nullptr); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) @@ -1437,7 +1471,7 @@ template <typename T> const char *GetPythonValueFormatString(T t) { assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type."); - return NULL; + return nullptr; } template <> const char *GetPythonValueFormatString (char *) { return "s"; } template <> const char *GetPythonValueFormatString (char) { return "b"; } @@ -1469,7 +1503,7 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - if (implementor == NULL || implementor == Py_None) + if (implementor == nullptr || implementor == Py_None) return lldb::ScriptInterpreterObjectSP(); PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); @@ -1479,7 +1513,7 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterOb PyErr_Clear(); } - if (pmeth == NULL || pmeth == Py_None) + if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); return lldb::ScriptInterpreterObjectSP(); @@ -1535,7 +1569,7 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); - if (implementor == NULL || implementor == Py_None) + if (implementor == nullptr || implementor == Py_None) return lldb::ScriptInterpreterObjectSP(); PyObject* pmeth = PyObject_GetAttrString(implementor, callee_name); @@ -1545,7 +1579,7 @@ ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP PyErr_Clear(); } - if (pmeth == NULL || pmeth == Py_None) + if (pmeth == nullptr || pmeth == Py_None) { Py_XDECREF(pmeth); return lldb::ScriptInterpreterObjectSP(); @@ -1627,7 +1661,7 @@ lldb::ScriptInterpreterObjectSP ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name, lldb::ValueObjectSP valobj) { - if (class_name == NULL || class_name[0] == '\0') + if (class_name == nullptr || class_name[0] == '\0') return lldb::ScriptInterpreterObjectSP(); if (!valobj.get()) @@ -1675,25 +1709,29 @@ ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::stri } -bool +Error ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines (); StreamString sstr; - + Error error; if (user_input.GetSize() == 0) - return false; + { + error.SetErrorString("No input data."); + return error; + } std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions)); sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input)) - return false; + error = GenerateFunction(sstr.GetData(), user_input); + if (!error.Success()) + return error; // Store the name of the auto-generated function to be called. output.assign(auto_generated_function_name); - return true; + return error; } bool @@ -1709,7 +1747,7 @@ ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions)); sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input)) + if (!GenerateFunction(sstr.GetData(), user_input).Success()) return false; // Store the name of the auto-generated function to be called. @@ -1732,7 +1770,7 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, return false; } - void* old_callee = (callee_wrapper_sp ? callee_wrapper_sp->GetObject() : NULL); + void* old_callee = (callee_wrapper_sp ? callee_wrapper_sp->GetObject() : nullptr); void* new_callee = old_callee; bool ret_val; @@ -1764,6 +1802,21 @@ ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name, } +void +ScriptInterpreterPython::Clear () +{ + // Release any global variables that might have strong references to + // LLDB objects when clearing the python script interpreter. + Locker locker(this, + ScriptInterpreterPython::Locker::AcquireLock, + ScriptInterpreterPython::Locker::FreeAcquiredLock); + + // This may be called as part of Py_Finalize. In that case the modules are destroyed in random + // order and we can't guarantee that we can access these. + if (Py_IsInitialized()) + PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None"); +} + bool ScriptInterpreterPython::BreakpointCallbackFunction ( @@ -1914,10 +1967,10 @@ ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); void* child_ptr = g_swig_get_child_index (implementor,idx); - if (child_ptr != NULL && child_ptr != Py_None) + if (child_ptr != nullptr && child_ptr != Py_None) { lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); - if (sb_value_ptr == NULL) + if (sb_value_ptr == nullptr) Py_XDECREF(child_ptr); else ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); @@ -2006,15 +2059,15 @@ ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::Scr static std::string ReadPythonBacktrace (PyObject* py_backtrace) { - PyObject* traceback_module = NULL, - *stringIO_module = NULL, - *stringIO_builder = NULL, - *stringIO_buffer = NULL, - *printTB = NULL, - *printTB_args = NULL, - *printTB_result = NULL, - *stringIO_getvalue = NULL, - *printTB_string = NULL; + PyObject* traceback_module = nullptr, + *stringIO_module = nullptr, + *stringIO_builder = nullptr, + *stringIO_buffer = nullptr, + *printTB = nullptr, + *printTB_args = nullptr, + *printTB_result = nullptr, + *stringIO_getvalue = nullptr, + *printTB_string = nullptr; std::string retval("backtrace unavailable"); @@ -2028,7 +2081,7 @@ ReadPythonBacktrace (PyObject* py_backtrace) stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO"); if (stringIO_builder && stringIO_builder != Py_None) { - stringIO_buffer = PyObject_CallObject(stringIO_builder, NULL); + stringIO_buffer = PyObject_CallObject(stringIO_builder, nullptr); if (stringIO_buffer && stringIO_buffer != Py_None) { printTB = PyObject_GetAttrString(traceback_module, "print_tb"); @@ -2039,7 +2092,7 @@ ReadPythonBacktrace (PyObject* py_backtrace) stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue"); if (stringIO_getvalue && stringIO_getvalue != Py_None) { - printTB_string = PyObject_CallObject (stringIO_getvalue,NULL); + printTB_string = PyObject_CallObject (stringIO_getvalue,nullptr); if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string)) retval.assign(PyString_AsString(printTB_string)); } @@ -2393,29 +2446,20 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, { error.SetErrorString("invalid Debugger pointer"); return false; - } + } bool ret_val = false; std::string err_msg; - + { Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession, + Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), Locker::FreeLock | Locker::TearDownSession); SynchronicityHandler synch_handler(debugger_sp, synchronicity); - // we need to save the thread state when we first start the command - // because we might decide to interrupt it while some action is taking - // place outside of Python (e.g. printing to screen, waiting for the network, ...) - // in that case, _PyThreadState_Current will be NULL - and we would be unable - // to set the asynchronous exception - not a desirable situation - m_command_thread_state = _PyThreadState_Current; - - //PythonInputReaderManager py_input(this); - ret_val = g_swig_call_command (impl_function, m_dictionary_name.c_str(), debugger_sp, @@ -2443,7 +2487,7 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& std::string command(item); command += ".__doc__"; - char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully + char* result_ptr = nullptr; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully if (ExecuteOneLineWithReturn (command.c_str(), ScriptInterpreter::eScriptReturnTypeCharStrOrNone, @@ -2561,7 +2605,7 @@ ScriptInterpreterPython::InitializePrivate () FileSpec file_spec; char python_dir_path[PATH_MAX]; - if (Host::GetLLDBPath (ePathTypePythonDir, file_spec)) + if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec)) { std::string python_path("sys.path.insert(0,\""); size_t orig_len = python_path.length(); @@ -2572,8 +2616,8 @@ ScriptInterpreterPython::InitializePrivate () PyRun_SimpleString (python_path.c_str()); python_path.resize (orig_len); } - - if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, file_spec)) + + if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec)) { if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path))) { @@ -2585,7 +2629,7 @@ ScriptInterpreterPython::InitializePrivate () } } - PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line; from termios import *"); + PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line"); if (threads_already_initialized) { if (log) |