ScriptInterpreterPython initialization

Hi Greg,

I found a problem with my initialization refactor, so I want to get your advice before I commit it. The issue is related to the fact that inserts some code at the end to automatically call SBDebugger.Initialize() the first time anyone runs “import lldb”.

When using lldb from python. When using lldb from python, this means the user doesn’t have to call SBDebugger.Initialize() because “import lldb” will do it automatically. When using lldb the executable, we call SBDebugger::Initialize() explicitly, which results in a call to this line in ScriptInterpreterPython:

int old_count = Debugger::TestDebuggerRefCount ();

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”);

int new_count = Debugger::TestDebuggerRefCount ();

if (new_count > old_count)
Debugger::Terminate ();

Since this is the first time lldb is imported, it results in a call to SBDebugger::Initialize() again. This recursive call doesn’t do anything because it sees that g_initialized has been set to true already. But when it returns control back to the line after the PyRun_SimpleString(), it tests the new ref count against the old ref count and calls Debugger::Terminate. But, the ref count was previously 1, so this results in the debugger refcount being 0. In practice it turns out this doesn’t matter, because all Debugger::Terminate() does is clear an already clear debugger list. And actually I can fix it by changing SystemLifetimeManager::AddRef() to put the call to Debugger::Initialize() before the call to m_initializer->Initialize().

But all of this is very fragile and confusing. I have an idea for fixing this a “better” way, but I would like your opinion.

If we remove the call to SBDebugger.Initialize() from (by changing to not insert these lines) the problems disappear. Now, when we write PyRun_SimpleString(“import lldb”) we don’t get a recursive call to SBDebugger::Initialize(). We would need to update the test suite to explicitly call this.

I think this makes for a more clear usage pattern. implicitly calling SBDebugger.Initialize() just seems like a bad idea. By making this change we would be able to remove all of the debugger ref count testing and conditionally calling Debugger::Terminate.


My main concern is "things should just work". Python expects functions to be ready to be called after importing so I would like to not require people to call SBDebugger::Initialize() first after a "import lldb". What ever we have to do to make this work, we should do that.

I don't know of _any_ other python module that requires you to call some function after importing the module, so it makes sense from a C++ API perspective, but not for python.

So I would vote to do what you need to do to make the following two things happen:
- from python when it loads LLDB "import lldb" should be enough
- in the embedded interpreter we should obviously not have to call it

From the Python API perspective, is there any way to use the SB APIs without first creating an SBDebugger() by calling SBDebugger.Create()? If the answer is no, then could we have the C++ implementation of SBDebugger.Create() call SBDebugger::Initialize? I haven’t actually tried to do that and see if it causes other issues, but it seems like a reasonable approach if it works.

Because we say people must call SBDebugger::Initialize() when using C++ I don't want to do this. There are tools in Apple that use LLDB by calling SBDebugger::Initialize(), do stuff that loads boat loads of stuff in memory, then they call SBDebugger::Terminate() and the memory frees up. We can't break that flow by having SBDebugger::Create() bump the ref count and stopping the terminate from working.