[lldb] Initialize Python exactly once
We got a few crash reports that showed LLDB initializing Python on two separate threads. Make sure Python is initialized exactly once. rdar://87287005 Differential revision: https://reviews.llvm.org/D117601
This commit is contained in:
parent
85c2bd2a0e
commit
eb5c0ea681
@ -85,8 +85,6 @@ static ScriptInterpreterPythonImpl *GetPythonInterpreter(Debugger &debugger) {
|
|||||||
return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);
|
return static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool g_initialized = false;
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Initializing Python is not a straightforward process. We cannot control
|
// Initializing Python is not a straightforward process. We cannot control
|
||||||
@ -219,6 +217,28 @@ private:
|
|||||||
PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
|
PyGILState_STATE m_gil_state = PyGILState_UNLOCKED;
|
||||||
bool m_was_already_initialized = false;
|
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
|
} // namespace
|
||||||
|
|
||||||
void ScriptInterpreterPython::ComputePythonDirForApple(
|
void ScriptInterpreterPython::ComputePythonDirForApple(
|
||||||
@ -333,12 +353,12 @@ llvm::StringRef ScriptInterpreterPython::GetPluginDescriptionStatic() {
|
|||||||
|
|
||||||
void ScriptInterpreterPython::Initialize() {
|
void ScriptInterpreterPython::Initialize() {
|
||||||
static llvm::once_flag g_once_flag;
|
static llvm::once_flag g_once_flag;
|
||||||
|
|
||||||
llvm::call_once(g_once_flag, []() {
|
llvm::call_once(g_once_flag, []() {
|
||||||
PluginManager::RegisterPlugin(GetPluginNameStatic(),
|
PluginManager::RegisterPlugin(GetPluginNameStatic(),
|
||||||
GetPluginDescriptionStatic(),
|
GetPluginDescriptionStatic(),
|
||||||
lldb::eScriptLanguagePython,
|
lldb::eScriptLanguagePython,
|
||||||
ScriptInterpreterPythonImpl::CreateInstance);
|
ScriptInterpreterPythonImpl::CreateInstance);
|
||||||
|
ScriptInterpreterPythonImpl::Initialize();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,8 +435,6 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)
|
|||||||
m_active_io_handler(eIOHandlerNone), m_session_is_active(false),
|
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_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0),
|
||||||
m_command_thread_state(nullptr) {
|
m_command_thread_state(nullptr) {
|
||||||
InitializePrivate();
|
|
||||||
|
|
||||||
m_scripted_process_interface_up =
|
m_scripted_process_interface_up =
|
||||||
std::make_unique<ScriptedProcessPythonInterface>(*this);
|
std::make_unique<ScriptedProcessPythonInterface>(*this);
|
||||||
|
|
||||||
@ -3151,36 +3169,7 @@ ScriptInterpreterPythonImpl::AcquireInterpreterLock() {
|
|||||||
return py_lock;
|
return py_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LLDB_USE_PYTHON_SET_INTERRUPT
|
void ScriptInterpreterPythonImpl::Initialize() {
|
||||||
namespace {
|
|
||||||
/// 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");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void ScriptInterpreterPythonImpl::InitializePrivate() {
|
|
||||||
if (g_initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_initialized = true;
|
|
||||||
|
|
||||||
LLDB_SCOPED_TIMER();
|
LLDB_SCOPED_TIMER();
|
||||||
|
|
||||||
// RAII-based initialization which correctly handles multiple-initialization,
|
// RAII-based initialization which correctly handles multiple-initialization,
|
||||||
|
@ -341,7 +341,7 @@ public:
|
|||||||
static bool WatchpointCallbackFunction(void *baton,
|
static bool WatchpointCallbackFunction(void *baton,
|
||||||
StoppointCallbackContext *context,
|
StoppointCallbackContext *context,
|
||||||
lldb::user_id_t watch_id);
|
lldb::user_id_t watch_id);
|
||||||
static void InitializePrivate();
|
static void Initialize();
|
||||||
|
|
||||||
class SynchronicityHandler {
|
class SynchronicityHandler {
|
||||||
private:
|
private:
|
||||||
|
@ -22,7 +22,6 @@ using namespace lldb_private;
|
|||||||
class TestScriptInterpreterPython : public ScriptInterpreterPythonImpl {
|
class TestScriptInterpreterPython : public ScriptInterpreterPythonImpl {
|
||||||
public:
|
public:
|
||||||
using ScriptInterpreterPythonImpl::Initialize;
|
using ScriptInterpreterPythonImpl::Initialize;
|
||||||
using ScriptInterpreterPythonImpl::InitializePrivate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void PythonTestSuite::SetUp() {
|
void PythonTestSuite::SetUp() {
|
||||||
@ -31,7 +30,6 @@ void PythonTestSuite::SetUp() {
|
|||||||
// ScriptInterpreterPython::Initialize() depends on HostInfo being
|
// ScriptInterpreterPython::Initialize() depends on HostInfo being
|
||||||
// initializedso it can compute the python directory etc.
|
// initializedso it can compute the python directory etc.
|
||||||
TestScriptInterpreterPython::Initialize();
|
TestScriptInterpreterPython::Initialize();
|
||||||
TestScriptInterpreterPython::InitializePrivate();
|
|
||||||
|
|
||||||
// Although we don't care about concurrency for the purposes of running
|
// Although we don't care about concurrency for the purposes of running
|
||||||
// this test suite, Python requires the GIL to be locked even for
|
// this test suite, Python requires the GIL to be locked even for
|
||||||
|
Loading…
x
Reference in New Issue
Block a user