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

Paul Peet via lldb-dev lldb-dev at lists.llvm.org
Mon Mar 28 11:48:08 PDT 2016


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