[Lldb-commits] [lldb] r142802 - in /lldb/trunk: include/lldb/Interpreter/ScriptInterpreterPython.h source/Interpreter/ScriptInterpreterPython.cpp
Enrico Granata
granata.enrico at gmail.com
Mon Oct 24 10:22:21 PDT 2011
Author: enrico
Date: Mon Oct 24 12:22:21 2011
New Revision: 142802
URL: http://llvm.org/viewvc/llvm-project?rev=142802&view=rev
Log:
Decoupling of lock-related code from the core of ScriptInterpreterPython. All that concerns locking the Python interpreter is now delegated to the internal ScriptInterpreterPython::Locker class. Several changes in ScriptInterpreterPython to accommodate this new pattern.
Modified:
lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=142802&r1=142801&r2=142802&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original)
+++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Mon Oct 24 12:22:21 2011
@@ -161,19 +161,50 @@
class Locker
{
public:
- Locker (ScriptInterpreterPython *py_interpreter,
- FILE* wait_msg_handle = NULL,
- bool need_session = true);
-
- bool
- HasAcquiredLock ()
- {
- return m_release_lock;
- }
-
+
+ enum OnEntry
+ {
+ AcquireLock = 0x0001,
+ InitSession = 0x0002
+ };
+
+ enum OnLeave
+ {
+ FreeLock = 0x0001,
+ FreeAcquiredLock = 0x0002, // do not free the lock if we already held it when calling constructor
+ TearDownSession = 0x0004
+ };
+
+ Locker (ScriptInterpreterPython *py_interpreter = NULL,
+ uint16_t on_entry = AcquireLock | InitSession,
+ uint16_t on_leave = FreeLock | TearDownSession,
+ FILE* wait_msg_handle = NULL);
+
~Locker ();
+ static bool
+ CurrentThreadHasPythonLock ();
+
private:
+
+ bool
+ DoAcquireLock ();
+
+ bool
+ DoInitSession ();
+
+ bool
+ DoFreeLock ();
+
+ bool
+ DoTearDownSession ();
+
+ static bool
+ TryGetPythonLock (uint32_t seconds_to_wait);
+
+ static void
+ ReleasePythonLock ();
+
bool m_need_session;
bool m_release_lock;
ScriptInterpreterPython *m_python_interpreter;
Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=142802&r1=142801&r2=142802&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)
+++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Mon Oct 24 12:22:21 2011
@@ -63,8 +63,8 @@
return g_interpreter_is_running;
}
-static bool
-CurrentThreadHasPythonLock ()
+bool
+ScriptInterpreterPython::Locker::CurrentThreadHasPythonLock ()
{
TimeValue timeout;
@@ -73,8 +73,8 @@
return PythonMutexPredicate().WaitForValueEqualTo (Host::GetCurrentThreadID(), &timeout, NULL);
}
-static bool
-GetPythonLock (uint32_t seconds_to_wait)
+bool
+ScriptInterpreterPython::Locker::TryGetPythonLock (uint32_t seconds_to_wait)
{
TimeValue timeout;
@@ -89,40 +89,88 @@
Host::GetCurrentThreadID(), &timeout, NULL);
}
-static void
-ReleasePythonLock ()
+void
+ScriptInterpreterPython::Locker::ReleasePythonLock ()
{
PythonMutexPredicate().SetValue (LLDB_INVALID_THREAD_ID, eBroadcastAlways);
}
-ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *pi,
- FILE* tmp_fh,
- bool ns) :
- m_need_session(ns),
- m_release_lock(false),
- m_python_interpreter(pi),
- m_tmp_fh(tmp_fh)
+ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
+ uint16_t on_entry,
+ uint16_t on_leave,
+ FILE* wait_msg_handle) :
+ m_need_session( (on_leave & TearDownSession) == TearDownSession ),
+ m_release_lock ( false ), // decide in constructor body
+ m_python_interpreter(py_interpreter),
+ m_tmp_fh(wait_msg_handle)
+{
+ if (m_python_interpreter && !m_tmp_fh)
+ m_tmp_fh = (m_python_interpreter->m_dbg_stdout ? m_python_interpreter->m_dbg_stdout : stdout);
+
+ if ( (on_entry & AcquireLock) == AcquireLock )
+ {
+ if (CurrentThreadHasPythonLock())
+ {
+ if ( (on_leave & FreeLock) == FreeLock )
+ m_release_lock = true;
+ }
+ else
+ {
+ DoAcquireLock();
+ if ( (on_leave & FreeLock) == FreeLock )
+ m_release_lock = true;
+ if ( (on_leave & FreeAcquiredLock) == FreeAcquiredLock )
+ m_release_lock = true;
+ }
+ }
+ if ( (on_entry & InitSession) == InitSession )
+ DoInitSession();
+}
+
+bool
+ScriptInterpreterPython::Locker::DoAcquireLock()
{
- // if Enter/LeaveSession() must be called, then m_python_interpreter must be != NULL
- assert(m_need_session && m_python_interpreter);
if (!CurrentThreadHasPythonLock())
{
- while (!GetPythonLock (1))
- if (tmp_fh)
- fprintf (tmp_fh,
+ while (!TryGetPythonLock (1))
+ if (m_tmp_fh)
+ fprintf (m_tmp_fh,
"Python interpreter locked on another thread; waiting to acquire lock...\n");
- m_release_lock = true;
}
- if (m_need_session)
- m_python_interpreter->EnterSession ();
+ return true;
+}
+
+bool
+ScriptInterpreterPython::Locker::DoInitSession()
+{
+ if (!m_python_interpreter)
+ return false;
+ m_python_interpreter->EnterSession ();
+ return true;
+}
+
+bool
+ScriptInterpreterPython::Locker::DoFreeLock()
+{
+ ReleasePythonLock ();
+ return true;
+}
+
+bool
+ScriptInterpreterPython::Locker::DoTearDownSession()
+{
+ if (!m_python_interpreter)
+ return false;
+ m_python_interpreter->LeaveSession ();
+ return true;
}
ScriptInterpreterPython::Locker::~Locker()
{
if (m_need_session)
- m_python_interpreter->LeaveSession ();
+ DoTearDownSession();
if (m_release_lock)
- ReleasePythonLock ();
+ DoFreeLock();
}
ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
@@ -145,33 +193,11 @@
g_initialized = true;
ScriptInterpreterPython::InitializePrivate ();
}
-
- bool safe_to_run = false;
- bool need_to_release_lock = true;
- int interval = 5; // Number of seconds to try getting the Python lock before timing out.
-
- // We don't dare exit this function without finishing setting up the script interpreter, so we must wait until
- // we can get the Python lock.
- if (CurrentThreadHasPythonLock())
- {
- safe_to_run = true;
- need_to_release_lock = false;
- }
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
- while (!safe_to_run)
- {
- safe_to_run = GetPythonLock (interval);
- if (!safe_to_run)
- {
- FILE *tmp_fh = (m_dbg_stdout ? m_dbg_stdout : stdout);
- fprintf (tmp_fh,
- "Python interpreter is locked on another thread; "
- "please release interpreter in order to continue.\n");
- interval = interval * 2;
- }
- }
-
m_dictionary_name.append("_dict");
StreamString run_string;
run_string.Printf ("%s = dict()", m_dictionary_name.c_str());
@@ -221,9 +247,6 @@
{
m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
}
-
- if (need_to_release_lock)
- ReleasePythonLock();
}
ScriptInterpreterPython::~ScriptInterpreterPython ()
@@ -242,16 +265,10 @@
if (m_new_sysout)
{
- FILE *tmp_fh = (m_dbg_stdout ? m_dbg_stdout : stdout);
- if (!CurrentThreadHasPythonLock ())
- {
- while (!GetPythonLock (1))
- fprintf (tmp_fh, "Python interpreter locked on another thread; waiting to acquire lock...\n");
- Py_DECREF ((PyObject*)m_new_sysout);
- ReleasePythonLock ();
- }
- else
- Py_DECREF ((PyObject*)m_new_sysout);
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeLock);
+ Py_DECREF ((PyObject*)m_new_sysout);
}
}
@@ -263,9 +280,7 @@
m_dbg_stdout = fh;
- FILE *tmp_fh = (m_dbg_stdout ? m_dbg_stdout : stdout);
-
- Locker py_lock(this, tmp_fh);
+ Locker py_lock(this);
m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
}
@@ -290,8 +305,6 @@
m_terminal_state.Restore();
}
-
-
void
ScriptInterpreterPython::LeaveSession ()
{
@@ -389,26 +402,15 @@
if (!m_valid_session)
return false;
-
-
// We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through
// PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside
// another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated
// method to pass the command string directly down to Python.
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
- bool need_to_release_lock = true;
-
- if (CurrentThreadHasPythonLock())
- need_to_release_lock = false;
- else if (!GetPythonLock (1))
- {
- fprintf ((m_dbg_stdout ? m_dbg_stdout : stdout),
- "Python interpreter is currently locked by another thread; unable to process command.\n");
- return false;
- }
-
- EnterSession ();
bool success = false;
if (command)
@@ -492,11 +494,6 @@
}
}
- LeaveSession ();
-
- if (need_to_release_lock)
- ReleasePythonLock();
-
if (success)
return true;
@@ -506,18 +503,11 @@
return false;
}
- LeaveSession ();
-
- if (need_to_release_lock)
- ReleasePythonLock ();
-
if (result)
result->AppendError ("empty command passed to python\n");
return false;
}
-
-
size_t
ScriptInterpreterPython::InputReaderCallback
(
@@ -535,7 +525,7 @@
return 0;
ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
-
+
if (script_interpreter->m_script_lang != eScriptLanguagePython)
return 0;
@@ -559,18 +549,11 @@
script_interpreter->SaveTerminalState(input_fd);
- if (!CurrentThreadHasPythonLock())
{
- while (!GetPythonLock(1))
- {
- out_stream->Printf ("Python interpreter locked on another thread; waiting to acquire lock...\n");
- out_stream->Flush();
- }
- script_interpreter->EnterSession ();
- ReleasePythonLock();
+ ScriptInterpreterPython::Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
}
- else
- script_interpreter->EnterSession ();
char error_str[1024];
if (script_interpreter->m_embedded_python_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
@@ -610,17 +593,11 @@
break;
case eInputReaderReactivate:
- if (!CurrentThreadHasPythonLock())
{
- while (!GetPythonLock(1))
- {
- // Wait until lock is acquired.
- }
- script_interpreter->EnterSession ();
- ReleasePythonLock();
+ ScriptInterpreterPython::Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
}
- else
- script_interpreter->EnterSession ();
break;
case eInputReaderAsynchronousOutputWritten:
@@ -716,18 +693,9 @@
void *ret_value)
{
- bool need_to_release_lock = true;
-
- if (CurrentThreadHasPythonLock())
- need_to_release_lock = false;
- else if (!GetPythonLock (1))
- {
- fprintf ((m_dbg_stdout ? m_dbg_stdout : stdout),
- "Python interpreter is currently locked by another thread; unable to process command.\n");
- return false;
- }
-
- EnterSession ();
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
PyObject *py_return = NULL;
PyObject *mainmod = PyImport_AddModule ("__main__");
@@ -896,11 +864,6 @@
PyErr_Clear();
ret_success = false;
}
-
- LeaveSession ();
-
- if (need_to_release_lock)
- ReleasePythonLock();
return ret_success;
}
@@ -908,18 +871,11 @@
bool
ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string)
{
- FILE *tmp_fh = (m_dbg_stdout ? m_dbg_stdout : stdout);
- bool need_to_release_lock = true;
-
- if (CurrentThreadHasPythonLock())
- need_to_release_lock = false;
- else
- {
- while (!GetPythonLock (1))
- fprintf (tmp_fh, "Python interpreter locked on another thread; waiting to acquire lock...\n");
- }
-
- EnterSession ();
+
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
bool success = false;
PyObject *py_return = NULL;
@@ -990,11 +946,6 @@
success = false;
}
- LeaveSession ();
-
- if (need_to_release_lock)
- ReleasePythonLock();
-
return success;
}
@@ -1303,7 +1254,7 @@
return false;
// Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
- // ValueObject as parameter to the function.
+ // required data as parameters to the function.
sstr.Printf ("lldb_autogen_python_cmd_alias_func_%d", num_created_functions);
++num_created_functions;
@@ -1425,11 +1376,9 @@
return NULL;
void* ret_val;
-
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
+
{
- Locker py_lock(this, tmp_fh);
+ Locker py_lock(this);
ret_val = g_swig_synthetic_script (class_name,
python_interpreter->m_dictionary_name.c_str(),
valobj);
@@ -1539,10 +1488,8 @@
if (python_function_name
&& *python_function_name)
{
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(python_interpreter);
ret_val = g_swig_typescript_callback (python_function_name,
python_interpreter->m_dictionary_name.c_str(),
valobj);
@@ -1594,10 +1541,8 @@
if (stop_frame_sp && bp_loc_sp)
{
bool ret_val = true;
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(python_interpreter);
ret_val = g_swig_breakpoint_callback (python_function_name,
python_interpreter->m_dictionary_name.c_str(),
stop_frame_sp,
@@ -1624,31 +1569,15 @@
char error_str[1024];
const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
- bool need_to_release_lock = true;
- bool safe_to_run = false;
- if (CurrentThreadHasPythonLock())
- {
- safe_to_run = true;
- need_to_release_lock = false;
- }
- else
- {
- int interval = 1;
- safe_to_run = GetPythonLock (interval);
- while (!safe_to_run)
- {
- interval = interval * 2;
- safe_to_run = GetPythonLock (interval);
- }
- }
-
- if (pty_slave_name != NULL && safe_to_run)
+ Locker locker(script_interpreter,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
+ if (pty_slave_name != NULL)
{
StreamString run_string;
- script_interpreter->EnterSession ();
-
run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
@@ -1697,18 +1626,9 @@
run_string.Printf ("run_one_line (%s, 'sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
-
- script_interpreter->LeaveSession ();
}
- if (!safe_to_run)
- fprintf ((script_interpreter->m_dbg_stdout ? script_interpreter->m_dbg_stdout : stdout),
- "Python interpreter locked on another thread; unable to acquire lock.\n");
-
- if (need_to_release_lock)
- ReleasePythonLock ();
-
if (script_interpreter->m_embedded_thread_input_reader_sp)
script_interpreter->m_embedded_thread_input_reader_sp->SetIsDone (true);
@@ -1738,15 +1658,11 @@
if (!g_swig_calc_children)
return 0;
-
- ScriptInterpreterPython *python_interpreter = this;
-
+
uint32_t ret_val = 0;
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(this);
ret_val = g_swig_calc_children (implementor);
}
@@ -1762,16 +1678,12 @@
if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
return lldb::ValueObjectSP();
- ScriptInterpreterPython *python_interpreter = this;
-
void* child_ptr = NULL;
lldb::SBValue* value_sb = NULL;
lldb::ValueObjectSP ret_val;
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(this);
child_ptr = g_swig_get_child_index (implementor,idx);
if (child_ptr != NULL && child_ptr != Py_None)
{
@@ -1799,14 +1711,10 @@
if (!g_swig_get_index_child)
return UINT32_MAX;
- ScriptInterpreterPython *python_interpreter = this;
-
int ret_val = UINT32_MAX;
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(this);
ret_val = g_swig_get_index_child (implementor, child_name);
}
@@ -1822,12 +1730,8 @@
if (!g_swig_update_provider)
return;
- ScriptInterpreterPython *python_interpreter = this;
-
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(this);
g_swig_update_provider (implementor);
}
@@ -1850,14 +1754,10 @@
return false;
}
- ScriptInterpreterPython *python_interpreter = this;
-
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().GetSP();
-
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
+
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(this);
FileSpec target_file(pathname, true);
@@ -1877,7 +1777,7 @@
command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.append('%s');\n\n",
directory,
directory);
- bool syspath_retval = python_interpreter->ExecuteMultipleLines(command_stream.GetData());
+ bool syspath_retval = ExecuteMultipleLines(command_stream.GetData());
if (!syspath_retval)
{
error.SetErrorString("Python sys.path handling failed");
@@ -1897,7 +1797,7 @@
int refcount = 0;
// this call will fail if the module does not exist (because the parameter to it is not a string
// but an actual Python module object, which is non-existant if the module was not imported before)
- if (python_interpreter->ExecuteOneLineWithReturn(command_stream.GetData(),
+ if (ExecuteOneLineWithReturn(command_stream.GetData(),
ScriptInterpreterPython::eScriptReturnTypeInt, &refcount) && refcount > 0)
{
error.SetErrorString("module already imported");
@@ -1907,7 +1807,7 @@
// now actually do the import
command_stream.Clear();
command_stream.Printf("import %s",basename.c_str());
- bool import_retval = python_interpreter->ExecuteOneLine(command_stream.GetData(), NULL);
+ bool import_retval = ExecuteOneLine(command_stream.GetData(), NULL);
if (!import_retval)
{
error.SetErrorString("Python import statement failed");
@@ -1916,7 +1816,7 @@
// call __lldb_module_init(debugger,dict)
if (!g_swig_call_module_init (basename,
- python_interpreter->m_dictionary_name.c_str(),
+ m_dictionary_name.c_str(),
debugger_sp))
{
error.SetErrorString("calling __lldb_module_init failed");
@@ -1944,20 +1844,16 @@
return false;
}
- ScriptInterpreterPython *python_interpreter = this;
-
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().GetSP();
bool ret_val;
std::string err_msg;
- FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout);
-
{
- Locker py_lock(python_interpreter, tmp_fh);
+ Locker py_lock(this);
ret_val = g_swig_call_command (impl_function,
- python_interpreter->m_dictionary_name.c_str(),
+ m_dictionary_name.c_str(),
debugger_sp,
args,
err_msg,
More information about the lldb-commits
mailing list