diff options
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp')
-rw-r--r-- | lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp | 206 |
1 files changed, 122 insertions, 84 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 6afa4742698b..1bf647e4acfc 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -37,7 +37,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" -#include "lldb/Utility/ReproducerInstrumentation.h" +#include "lldb/Utility/Instrumentation.h" #include "lldb/Utility/Timer.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -70,6 +70,14 @@ extern "C" void init_lldb(void); #define LLDBSwigPyInit init_lldb #endif +#if defined(_WIN32) +// Don't mess with the signal handlers on Windows. +#define LLDB_USE_PYTHON_SET_INTERRUPT 0 +#else +// PyErr_SetInterrupt was introduced in 3.2. +#define LLDB_USE_PYTHON_SET_INTERRUPT \ + (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3) +#endif static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { ScriptInterpreter *script_interpreter = @@ -77,8 +85,6 @@ static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) { return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter); } -static bool g_initialized = false; - namespace { // Initializing Python is not a straightforward process. We cannot control @@ -211,6 +217,28 @@ private: PyGILState_STATE m_gil_state = PyGILState_UNLOCKED; bool m_was_already_initialized = false; }; + +#if LLDB_USE_PYTHON_SET_INTERRUPT +/// Saves the current signal handler for the specified signal and restores +/// it at the end of the current scope. +struct RestoreSignalHandlerScope { + /// The signal handler. + struct sigaction m_prev_handler; + int m_signal_code; + RestoreSignalHandlerScope(int signal_code) : m_signal_code(signal_code) { + // Initialize sigaction to their default state. + std::memset(&m_prev_handler, 0, sizeof(m_prev_handler)); + // Don't install a new handler, just read back the old one. + struct sigaction *new_handler = nullptr; + int signal_err = ::sigaction(m_signal_code, new_handler, &m_prev_handler); + lldbassert(signal_err == 0 && "sigaction failed to read handler"); + } + ~RestoreSignalHandlerScope() { + int signal_err = ::sigaction(m_signal_code, &m_prev_handler, nullptr); + lldbassert(signal_err == 0 && "sigaction failed to restore old handler"); + } +}; +#endif } // namespace void ScriptInterpreterPython::ComputePythonDirForApple( @@ -325,12 +353,12 @@ llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() { void ScriptInterpreterPython::Initialize() { static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), lldb::eScriptLanguagePython, ScriptInterpreterPythonImpl::CreateInstance); + ScriptInterpreterPythonImpl::Initialize(); }); } @@ -342,7 +370,6 @@ ScriptInterpreterPythonImpl::Locker::Locker( : ScriptInterpreterLocker(), m_teardown_session((on_leave & TearDownSession) == TearDownSession), m_python_interpreter(py_interpreter) { - repro::Recorder::PrivateThread(); DoAcquireLock(); if ((on_entry & InitSession) == InitSession) { if (!DoInitSession(on_entry, in, out, err)) { @@ -408,8 +435,6 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_active_io_handler(eIOHandlerNone), m_session_is_active(false), m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0), m_command_thread_state(nullptr) { - InitializePrivate(); - m_scripted_process_interface_up = std::make_unique<ScriptedProcessPythonInterface>(*this); @@ -921,6 +946,22 @@ void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() { } bool ScriptInterpreterPythonImpl::Interrupt() { +#if LLDB_USE_PYTHON_SET_INTERRUPT + // If the interpreter isn't evaluating any Python at the moment then return + // false to signal that this function didn't handle the interrupt and the + // next component should try handling it. + if (!IsExecutingPython()) + return false; + + // Tell Python that it should pretend to have received a SIGINT. + PyErr_SetInterrupt(); + // PyErr_SetInterrupt has no way to return an error so we can only pretend the + // signal got successfully handled and return true. + // Python 3.10 introduces PyErr_SetInterruptEx that could return an error, but + // the error handling is limited to checking the arguments which would be + // just our (hardcoded) input signal code SIGINT, so that's not useful at all. + return true; +#else Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT)); if (IsExecutingPython()) { @@ -942,6 +983,7 @@ bool ScriptInterpreterPythonImpl::Interrupt() { "ScriptInterpreterPythonImpl::Interrupt() python code not running, " "can't interrupt"); return false; +#endif } bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn( @@ -1414,16 +1456,12 @@ ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) { if (class_name == nullptr || class_name[0] == '\0') return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - ret_val = LLDBSWIGPython_CreateFrameRecognizer(class_name, - m_dictionary_name.c_str()); - } + Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); + PythonObject ret_val = LLDBSWIGPython_CreateFrameRecognizer( + class_name, m_dictionary_name.c_str()); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( @@ -1478,16 +1516,12 @@ ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( if (!process_sp) return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - ret_val = LLDBSWIGPythonCreateOSPlugin( - class_name, m_dictionary_name.c_str(), process_sp); - } + Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); + PythonObject ret_val = LLDBSWIGPythonCreateOSPlugin( + class_name, m_dictionary_name.c_str(), process_sp); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( @@ -1733,19 +1767,16 @@ StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( if (!python_interpreter) return {}; - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedThreadPlan( - class_name, python_interpreter->m_dictionary_name.c_str(), - args_data, error_str, thread_plan_sp); - if (!ret_val) - return {}; - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + PythonObject ret_val = LLDBSwigPythonCreateScriptedThreadPlan( + class_name, python_interpreter->m_dictionary_name.c_str(), args_data, + error_str, thread_plan_sp); + if (!ret_val) + return {}; - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); + return StructuredData::ObjectSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop( @@ -1836,18 +1867,15 @@ ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( if (!python_interpreter) return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedBreakpointResolver( - class_name, python_interpreter->m_dictionary_name.c_str(), args_data, - bkpt_sp); - } + PythonObject ret_val = LLDBSwigPythonCreateScriptedBreakpointResolver( + class_name, python_interpreter->m_dictionary_name.c_str(), args_data, + bkpt_sp); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback( @@ -1911,18 +1939,15 @@ StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook( return StructuredData::GenericSP(); } - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateScriptedStopHook( - target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), - args_data, error); - } + PythonObject ret_val = LLDBSwigPythonCreateScriptedStopHook( + target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), + args_data, error); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop( @@ -2011,16 +2036,13 @@ ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider( if (!python_interpreter) return StructuredData::ObjectSP(); - void *ret_val = nullptr; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateSyntheticProvider( - class_name, python_interpreter->m_dictionary_name.c_str(), valobj); - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + PythonObject ret_val = LLDBSwigPythonCreateSyntheticProvider( + class_name, python_interpreter->m_dictionary_name.c_str(), valobj); - return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); + return StructuredData::ObjectSP( + new StructuredPythonObject(std::move(ret_val))); } StructuredData::GenericSP @@ -2033,16 +2055,13 @@ ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) { if (!debugger_sp.get()) return StructuredData::GenericSP(); - void *ret_val; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonCreateCommandObject( - class_name, m_dictionary_name.c_str(), debugger_sp); - } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + PythonObject ret_val = LLDBSwigPythonCreateCommandObject( + class_name, m_dictionary_name.c_str(), debugger_sp); - return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); } bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( @@ -2152,8 +2171,12 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( return false; } - if (new_callee && old_callee != new_callee) - callee_wrapper_sp = std::make_shared<StructuredPythonObject>(new_callee); + if (new_callee && old_callee != new_callee) { + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + callee_wrapper_sp = std::make_shared<StructuredPythonObject>( + PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(new_callee))); + } return ret_val; } @@ -2805,7 +2828,8 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( ScriptInterpreter::eScriptReturnTypeOpaqueObject, &module_pyobj, exc_options) && module_pyobj) - *module_sp = std::make_shared<StructuredPythonObject>(module_pyobj); + *module_sp = std::make_shared<StructuredPythonObject>(PythonObject( + PyRefType::Owned, static_cast<PyObject *>(module_pyobj))); } return true; @@ -3145,12 +3169,7 @@ ScriptInterpreterPythonImpl::AcquireInterpreterLock() { return py_lock; } -void ScriptInterpreterPythonImpl::InitializePrivate() { - if (g_initialized) - return; - - g_initialized = true; - +void ScriptInterpreterPythonImpl::Initialize() { LLDB_SCOPED_TIMER(); // RAII-based initialization which correctly handles multiple-initialization, @@ -3180,6 +3199,25 @@ void ScriptInterpreterPythonImpl::InitializePrivate() { "lldb.embedded_interpreter; from " "lldb.embedded_interpreter import run_python_interpreter; " "from lldb.embedded_interpreter import run_one_line"); + +#if LLDB_USE_PYTHON_SET_INTERRUPT + // Python will not just overwrite its internal SIGINT handler but also the + // one from the process. Backup the current SIGINT handler to prevent that + // Python deletes it. + RestoreSignalHandlerScope save_sigint(SIGINT); + + // Setup a default SIGINT signal handler that works the same way as the + // normal Python REPL signal handler which raises a KeyboardInterrupt. + // Also make sure to not pollute the user's REPL with the signal module nor + // our utility function. + PyRun_SimpleString("def lldb_setup_sigint_handler():\n" + " import signal;\n" + " def signal_handler(sig, frame):\n" + " raise KeyboardInterrupt()\n" + " signal.signal(signal.SIGINT, signal_handler);\n" + "lldb_setup_sigint_handler();\n" + "del lldb_setup_sigint_handler\n"); +#endif } void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location, |