[lldb-dev] SBListener not using a shared_ptr internally? (Update: Segfault after r262863)

Jim Ingham via lldb-dev lldb-dev at lists.llvm.org
Mon Mar 28 12:07:25 PDT 2016


Yes, that should work too.  The thing that doesn't work is to just let the C++ destructor chain tear down the debuggers you've made.  It should be possible to make that work, but nobody's had time to make that happen, and given you can avoid the crashes if you exit cleanly, it hasn't been a terribly high priority.

Jim

> On Mar 28, 2016, at 11:48 AM, Paul Peet <paulpeet17 at gmail.com> wrote:
> 
> Ah, Thanks adding Debugger::Destroy at the end of my code made the
> segfaults disappear.
> Also as far as I understood the lldb code (Core/Debugger.cpp) it
> should also be possible to call SBDebugger::Terminate() for "destroy"
> all instances of lldb related objects.
> 
> 2016-03-28 20:22 GMT+02:00 Jim Ingham <jingham at apple.com>:
>> lldb doesn't currently work if you leave the process of cleaning up to the C++ destructor chain.  You need to call Debugger::Destroy on your way out.
>> 
>> I think there's a bunch more cleanup than just the broadcaster/listener stuff before we'll do this right.
>> 
>> Jim
>> 
>>> On Mar 28, 2016, at 8:55 AM, Paul Peet <paulpeet17 at gmail.com> wrote:
>>> 
>>> Hey again,
>>> 
>>> I've noticing segfaults after r262863
>>> (dc5ef2da510f3adba99cd8b2fe18c2e6d417227d).
>>> Could you try reproducing this bug with this code please?
>>> 
>>> int main() {
>>> using namespace lldb;
>>> 
>>> SBDebugger::Initialize();
>>> 
>>> SBDebugger debugger = SBDebugger::Create(true);
>>> if(!debugger.IsValid()) {
>>>   return 1;
>>> }
>>> 
>>> SBTarget target = debugger.CreateTarget("/home/dev/helloWorld/main");
>>> if(!target.IsValid()) {
>>>   return 1;
>>> }
>>> 
>>> const char* args[] = { "/home/dev/helloWorld/main", 0 };
>>> const char* env[] = { 0 };
>>> 
>>> SBLaunchInfo launch_info(args);
>>> launch_info.SetEnvironmentEntries(env, true);
>>> launch_info.SetWorkingDirectory("/home/dev/helloWorld");
>>> launch_info.SetLaunchFlags(eLaunchFlagStopAtEntry);
>>> 
>>> SBError error;
>>> SBProcess process = target.Launch(launch_info, error);
>>> 
>>> return 0;
>>> }
>>> 
>>> I tried to build lldb with and without the above commit and it turns
>>> out that the revision is causing the segfault when simply running that
>>> code (When it's exiting).
>>> 
>>> This is the backtrace:
>>> 
>>> #0  0x0000555555b03b00 in ?? ()
>>> #1  0x00007ffff71be1aa in
>>> lldb_private::Broadcaster::BroadcasterImpl::RestoreBroadcaster() ()
>>> from /usr/lib/liblldb.so.3.8.0
>>> #2  0x00007ffff748b674 in
>>> lldb_private::process_gdb_remote::GDBRemoteCommunicationClient::SendPacketAndWaitForResponse(char
>>> const*, unsigned long, StringExtractorGDBRemote&, bool) () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #3  0x00007ffff748e89d in
>>> lldb_private::process_gdb_remote::GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(lldb_private::process_gdb_remote::GDBStoppointType,
>>> bool, unsigned long, unsigned int) () from /usr/lib/liblldb.so.3.8.0
>>> #4  0x00007ffff746fdab in
>>> lldb_private::process_gdb_remote::ProcessGDBRemote::DisableBreakpointSite(lldb_private::BreakpointSite*)
>>> () from /usr/lib/liblldb.so.3.8.0
>>> #5  0x00007ffff733938b in std::_Function_handler<void
>>> (lldb_private::BreakpointSite*),
>>> lldb_private::Process::DisableAllBreakpointSites()::{lambda(lldb_private::BreakpointSite*)#1}>::_M_invoke(std::_Any_data
>>> const&, lldb_private::BreakpointSite*&&) () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #6  0x00007ffff716ae4f in
>>> lldb_private::BreakpointSiteList::ForEach(std::function<void
>>> (lldb_private::BreakpointSite*)> const&) () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #7  0x00007ffff733ba9f in
>>> lldb_private::Process::DisableAllBreakpointSites() () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #8  0x00007ffff734a58c in lldb_private::Process::Destroy(bool) () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #9  0x00007ffff734aa2d in lldb_private::Process::Finalize() () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #10 0x00007ffff71d3fe0 in lldb_private::Debugger::Clear() () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #11 0x00007ffff71d97cf in lldb_private::Debugger::~Debugger() () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #12 0x00007ffff71da0c8 in
>>> std::_Sp_counted_ptr<lldb_private::Debugger*,
>>> (__gnu_cxx::_Lock_policy)2>::_M_dispose() () from
>>> /usr/lib/liblldb.so.3.8.0
>>> #13 0x00007ffff71cdceb in
>>> std::vector<std::shared_ptr<lldb_private::Debugger>,
>>> std::allocator<std::shared_ptr<lldb_private::Debugger> > >::~vector()
>>> () from /usr/lib/liblldb.so.3.8.0
>>> #14 0x00007ffff60d9c38 in __run_exit_handlers () from /usr/lib/libc.so.6
>>> #15 0x00007ffff60d9c85 in exit () from /usr/lib/libc.so.6
>>> #16 0x00007ffff60c4717 in __libc_start_main () from /usr/lib/libc.so.6
>>> #17 0x0000555555554f69 in _start ()
>>> 
>>> 2016-03-25 22:42 GMT+01:00 Jim Ingham <jingham at apple.com>:
>>>> What version of the lldb sources are you working with?  I changed the SBListener over to using only the ListenerSP internally
>>>> in r262863.
>>>> 
>>>> Jim
>>>> 
>>>>> On Mar 25, 2016, at 1:03 PM, Paul Peet via lldb-dev <lldb-dev at lists.llvm.org> wrote:
>>>>> 
>>>>> Hey,
>>>>> 
>>>>> I am currently working on lldb bindings for javascript (v8) but it
>>>>> seems that the API is giving me some troubles.
>>>>> 
>>>>> What I am doing is to basically wrap SB* objects into V8 objects, and
>>>>> since SB objects contain a shared_ptr into an internal class I think I
>>>>> can simply copy construct them.
>>>>> 
>>>>> To return a wrapped SB object by some Javascript function, I am simply
>>>>> copy constructing the SB object into the wrapper object which is
>>>>> dynamically allocated and when the Javascript object is garbage
>>>>> collected it will also destroy the SBObject (And also the shared_ptr,
>>>>> So it should be save I guess?).
>>>>> 
>>>>> Okay, so far so good but I detected some inconsistency when trying to
>>>>> wrap SBListener. The deal was to make SBListener::WaitForEvent
>>>>> non-blocking, to do that I am creating a new thread which calls
>>>>> WaitForEvents, when it returns and the event is valid, the callbacks
>>>>> given from the Javascript code is called.
>>>>> 
>>>>> There is a catch when doing this. I have to track the threads which
>>>>> belong to a specific SBListener. But there is not actually easy way to
>>>>> do this because SB objects are just simply shared_ptr. I noticed the
>>>>> GetSP function which returns the shared_ptr of an SBListener, this
>>>>> would be a way to solve this issue as I could use a map which maps the
>>>>> internal SBListener pointer to a Class object which manages the thread
>>>>> and stuff (SBListenerWorker).
>>>>> 
>>>>> // etc. mutex, ...
>>>>> static std::unordered_map<void*, SBListenerWorker*> ListenerWorkers;
>>>>> 
>>>>> GetSP is protected so I had to create a new derived class:
>>>>> 
>>>>> class SBListener_Internal : public lldb::SBListener {
>>>>> public:
>>>>> SBListener_Internal() = default;
>>>>> SBListener_Internal(const lldb::SBListener& listener)
>>>>>    : lldb::SBListener{listener} {
>>>>> }
>>>>> ~SBListener_Internal() = default;
>>>>> 
>>>>> void* GetInternalPtr() {
>>>>>  return reinterpret_cast<void*>(GetSP().get());
>>>>> }
>>>>> };
>>>>> 
>>>>> I had some worried about if the SBListener object could be destroyed
>>>>> at some point and the internal pointer would still be in the
>>>>> "ListenerWorkers" map so
>>>>> to avoid that I copied the the SBListener object into the class which
>>>>> manages the thread and stuff (SBListenerWorker), that means that the
>>>>> reference counter should be still > 0 when all other shared_ptrs are
>>>>> destroyed.
>>>>> 
>>>>> Now to the actual problem, it turns out that GetInternalPtr() actually
>>>>> returns nullptr and instead uses m_opaque_ptr for calling internal
>>>>> functions.
>>>>> This means that the SBListener object isn't actually using a
>>>>> shared_ptr internally, which brings another question up if it is save
>>>>> to use the SBListener across thread? What happens if the SBListener
>>>>> gets destroyed.
>>>>> _______________________________________________
>>>>> lldb-dev mailing list
>>>>> lldb-dev at lists.llvm.org
>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>>>> 
>> 



More information about the lldb-dev mailing list