<div dir="ltr">Thank you Pavel! That's interesting. <div>Not that urgent, I have a workaround for this issue. For the inferior, I just copied some random multithreading code from internet to demonstrate this issue, definitely a good way exit main thread :-). </div><div>Btw: I was surprised on Mac/Linux the whole process is still alive after main thread exits, I thought main thread C runtime will kill whole process, maybe it is <span style="font-size:12.8px">pthread_exit() that prevent C runtime from killing process</span>.(Sorry, newbie to Mac/Linux)</div><div><br></div><div>Jeffrey</div><div><div><div><br></div><div><br></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Apr 8, 2016 at 4:32 AM, Pavel Labath <span dir="ltr"><<a href="mailto:labath@google.com" target="_blank">labath@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Ok, so the reason for this behavior seems to be that the process hits<br>
two breakpoints simultaneously:<br>
- the breakpoint you have set and you are expecting to hit<br>
- an internal shared library breakpoint we use to get notified of new<br>
shared libraries<br>
<br>
* thread #1: tid = 33390, 0x00007ff7dcd9f970<br>
ld-linux-x86-64.so.2`_dl_debug_state, name = 'a.out', stop reason =<br>
shared-library-event<br>
  * frame #0: 0x00007ff7dcd9f970 ld-linux-x86-64.so.2`_dl_debug_state<br>
    frame #1: 0x00007ff7dcda3b05<br>
ld-linux-x86-64.so.2`___lldb_unnamed_symbol90$$ld-linux-x86-64.so.2 +<br>
357<br>
    frame #2: 0x00007ff7dcd9eff4<br>
ld-linux-x86-64.so.2`___lldb_unnamed_symbol59$$ld-linux-x86-64.so.2 +<br>
116<br>
    frame #3: 0x00007ff7dcda33bb<br>
ld-linux-x86-64.so.2`___lldb_unnamed_symbol88$$ld-linux-x86-64.so.2 +<br>
171<br>
    frame #4: 0x00007ff7dc5de0f2<br>
libc.so.6`do_dlopen(ptr=0x00007ffed953c6f0) + 66 at dl-libc.c:87<br>
    frame #5: 0x00007ff7dcd9eff4<br>
ld-linux-x86-64.so.2`___lldb_unnamed_symbol59$$ld-linux-x86-64.so.2 +<br>
116<br>
    frame #6: 0x00007ff7dc5de1b2 libc.so.6`__GI___libc_dlopen_mode +<br>
47 at dl-libc.c:46<br>
    frame #7: 0x00007ff7dc5de183<br>
libc.so.6`__GI___libc_dlopen_mode(name=<unavailable>,<br>
mode=<unavailable>) + 35 at dl-libc.c:163<br>
    frame #8: 0x00007ff7dc87da43 libpthread.so.0`pthread_cancel_init +<br>
35 at unwind-forcedunwind.c:52<br>
    frame #9: 0x00007ff7dc87dc0c<br>
libpthread.so.0`_Unwind_ForcedUnwind(exc=0x00007ff7dcf8ddf0,<br>
stop=(libpthread.so.0`unwind_stop at unwind.c:44),<br>
stop_argument=0x00007ffed953c7f0) + 60 at unwind-forcedunwind.c:129<br>
    frame #10: 0x00007ff7dc87bd40<br>
libpthread.so.0`__GI___pthread_unwind(buf=<unavailable>) + 64 at<br>
unwind.c:129<br>
    frame #11: 0x00007ff7dc876535 libpthread.so.0`__pthread_exit + 37<br>
at pthreadP.h:280<br>
    frame #12: 0x00007ff7dc87651d<br>
libpthread.so.0`__pthread_exit(value=<unavailable>) + 13 at<br>
pthread_exit.c:29<br>
    frame #13: 0x0000000000400b00 a.out`main + 186<br>
    frame #14: 0x00007ff7dc4c9ec5<br>
libc.so.6`__libc_start_main(main=(a.out`main), argc=1,<br>
argv=0x00007ffed953c8a8, init=<unavailable>, fini=<unavailable>,<br>
rtld_fini=<unavailable>, stack_end=0x00007ffed953c898) + 245 at<br>
libc-start.c:287<br>
    frame #15: 0x0000000000400939 a.out`_start + 41<br>
<br>
  thread #2: tid = 35166, 0x00000000004009fd a.out`PrintHello(void*),<br>
name = 'a.out', stop reason = breakpoint 1.1<br>
    frame #0: 0x00000000004009fd a.out`PrintHello(void*)<br>
    frame #1: 0x00007ff7dc875182<br>
libpthread.so.0`start_thread(arg=0x00007ff7dbf8b700) + 194 at<br>
pthread_create.c:312<br>
    frame #2: 0x00007ff7dc5a247d libc.so.6`__clone + 109 at clone.S:111<br>
<br>
<br>
These internal breakpoints are normally ignored, but I can certainly<br>
imagine that if you hit them concurrently with a regular breakpoint,<br>
the thread-selecting machinery will get confused. I don't have time to<br>
look into this more right now, but I'll get to it eventually if<br>
someone doesn't beat me to it...<br>
<br>
<br>
PS: Your inferior is quite strange. I am not sure you are allowed to<br>
exit the main thread via pthread_exit(), especially when you still<br>
have non-detached threads running...<br>
<span class="HOEnZb"><font color="#888888"><br>
pl<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
On 21 March 2016 at 05:03, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
> Thanks guys. I tried our IDE against a sample multithreading program on Mac,<br>
> it correctly switches selected thread to the worker thread that triggers<br>
> breakpoint, while on Linux(CentOS release 6.7) it failed to do that. Repro<br>
> code:<br>
><br>
> =========================Output=========================<br>
> Launch result: success<br>
> <Listener> Listening Thread ID: 139749072582400<br>
> running_signal wait<br>
> stopped_signal wait<br>
> Target event: ModulesLoaded<br>
> Target event: ModulesLoaded<br>
> Target event: ModulesLoaded<br>
> Target event: ModulesLoaded<br>
> Target event: ModulesLoaded<br>
> Target event: ModulesLoaded<br>
> Target event: ModulesLoaded<br>
> Target event: ModulesLoaded<br>
> Non stopping event: <lldb.SBEvent; proxy of <Swig Object of type<br>
> 'lldb::SBEvent *' at 0x7f19e0975990> ><br>
> Process event: StateChanged, Running<br>
> Stop reason: 1<br>
> Process event: Stdout, Running<br>
> Stop reason: 1<br>
> Stdout:<br>
> main() : creating thread, 0<br>
> Process event: StateChanged, Stopped<br>
> after wait_for_process_run_then_stop<br>
> frame #0: 0x00007fcb7259ceb0 ld-linux-x86-64.so.2`__GI__dl_debug_state<br>
> frame #1: 0x00007fcb725a0c53 ld-linux-x86-64.so.2`dl_open_worker + 499<br>
> frame #2: 0x00007fcb7259c286 ld-linux-x86-64.so.2`_dl_catch_error + 102<br>
> frame #3: 0x00007fcb725a063a ld-linux-x86-64.so.2`_dl_open + 186<br>
> frame #4: 0x00007fcb71963c60 libc.so.6`do_dlopen + 64<br>
> frame #5: 0x00007fcb7259c286 ld-linux-x86-64.so.2`_dl_catch_error + 102<br>
> frame #6: 0x00007fcb71963db7 libc.so.6`__GI___libc_dlopen_mode + 71<br>
> frame #7: 0x00007fcb71be0eec libpthread.so.0`pthread_cancel_init + 76<br>
> frame #8: 0x00007fcb71be104c libpthread.so.0`_Unwind_ForcedUnwind + 60<br>
> frame #9: 0x00007fcb71bdef60 libpthread.so.0`__GI___pthread_unwind + 64<br>
> frame #10: 0x00007fcb71bd9175 libpthread.so.0`__pthread_exit + 37<br>
> frame #11: 0x0000000000400ac0 threads`main + 195 at threads.cpp:31<br>
> frame #12: 0x00007fcb7185bd5d libc.so.6`__libc_start_main + 253<br>
> frame #13: 0x00000000004008f9 threads<br>
> <Listener> Exiting listener thread<br>
><br>
> =========================Inferior=========================<br>
> #include <iostream><br>
> #include <cstdlib><br>
> #include <pthread.h><br>
><br>
> using namespace std;<br>
><br>
> #define NUM_THREADS     1<br>
><br>
> void *PrintHello(void *threadid)<br>
> {<br>
>    long tid;<br>
>    tid = (long)threadid;<br>
>    cout << "Hello World! Thread ID, " << tid << endl;<br>
>    pthread_exit(NULL);<br>
> }<br>
><br>
> int main ()<br>
> {<br>
>    pthread_t threads[NUM_THREADS];<br>
>    int rc;<br>
>    int i;<br>
>    for( i=0; i < NUM_THREADS; i++ ){<br>
>       cout << "main() : creating thread, " << i << endl;<br>
>       rc = pthread_create(&threads[i], NULL,<br>
>                           PrintHello, (void *)i);<br>
>       if (rc){<br>
>          cout << "Error:unable to create thread," << rc << endl;<br>
>          exit(-1);<br>
>       }<br>
>    }<br>
>    pthread_exit(NULL);<br>
> }<br>
><br>
> =========================LLDB python automation<br>
> code=========================<br>
> main.py<br>
><br>
> # Should be first for LLDB package to be added to search path.<br>
> from find_lldb import lldb<br>
> import sys<br>
> import os<br>
> import time<br>
> from sys import stdin, stdout<br>
> from event_thread import LLDBListenerThread<br>
> import threading<br>
><br>
> def wait_for_process_run_then_stop(running_signal, stopped_signal):<br>
>     print 'running_signal wait'<br>
>     running_signal.wait()<br>
>     running_signal.clear()<br>
>     print 'stopped_signal wait'<br>
>     stopped_signal.wait()<br>
>     stopped_signal.clear()<br>
><br>
> def do_test():<br>
>     debugger = lldb.SBDebugger.Create()<br>
>     debugger.SetAsync(True)<br>
>     executable_path = '~/personal/cpp/temp/threads'<br>
>     target = debugger.CreateTargetWithFileAndArch(executable_path,<br>
> lldb.LLDB_ARCH_DEFAULT)<br>
>     target.BreakpointCreateByName('PrintHello')<br>
><br>
>     listener = lldb.SBListener('Event Listener')<br>
>     error = lldb.SBError()<br>
>     process = target.Launch (listener,<br>
>                              None,      # argv<br>
>                              None,      # envp<br>
>                              None,      # stdin_path<br>
>                              None,      # stdout_path<br>
>                              None,      # stderr_path<br>
>                              None,      # working directory<br>
>                              0,         # launch flags<br>
>                              False,     # Stop at entry<br>
>                              error)     # error<br>
>     print 'Launch result: %s' % str(error)<br>
><br>
>     running_signal = threading.Event()<br>
>     stopped_signal = threading.Event()<br>
>     running_signal.set()<br>
>     event_thread = LLDBListenerThread(debugger, running_signal,<br>
> stopped_signal)<br>
>     event_thread.start()<br>
><br>
>     wait_for_process_run_then_stop(running_signal, stopped_signal)<br>
><br>
>     print 'after wait_for_process_run_then_stop'<br>
>     activeThread = process.GetSelectedThread()<br>
>     for frame in activeThread.frames:<br>
>         print frame<br>
><br>
>     event_thread.should_quit = True<br>
>     event_thread.join()<br>
><br>
>     lldb.SBDebugger.Destroy(debugger)<br>
>     return debugger<br>
><br>
> def main():<br>
>     debugger = do_test()<br>
><br>
> if __name__ == '__main__':<br>
>     main()<br>
><br>
><br>
> ===========event_thread.py============<br>
><br>
> import lldb<br>
> from threading import Thread<br>
> from sys import stdout<br>
> import thread<br>
> import threading<br>
><br>
> target_event_type_to_name_map = {<br>
>     lldb.SBTarget.eBroadcastBitBreakpointChanged: 'BreakpointChanged',<br>
>     lldb.SBTarget.eBroadcastBitWatchpointChanged: 'WatchpointChanged',<br>
>     lldb.SBTarget.eBroadcastBitModulesLoaded: 'ModulesLoaded',<br>
>     lldb.SBTarget.eBroadcastBitModulesUnloaded: 'ModulesUnloaded',<br>
>     lldb.SBTarget.eBroadcastBitSymbolsLoaded: 'SymbolsLoaded',<br>
> }<br>
><br>
> process_event_type_to_name_map = {<br>
>     lldb.SBProcess.eBroadcastBitStateChanged: 'StateChanged',<br>
>     lldb.SBProcess.eBroadcastBitSTDOUT: 'Stdout',<br>
>     lldb.SBProcess.eBroadcastBitSTDERR: 'Stderr',<br>
>     lldb.SBProcess.eBroadcastBitInterrupt: 'Interupt',<br>
> }<br>
><br>
> breakpoint_event_type_to_name_map = {<br>
>     lldb.eBreakpointEventTypeAdded: 'Added',<br>
>     lldb.eBreakpointEventTypeCommandChanged: 'Command Changed',<br>
>     lldb.eBreakpointEventTypeConditionChanged: 'Condition Changed',<br>
>     lldb.eBreakpointEventTypeDisabled: 'Disabled',<br>
>     lldb.eBreakpointEventTypeEnabled: 'Enabled',<br>
>     lldb.eBreakpointEventTypeIgnoreChanged: 'Ignore Changed',<br>
>     lldb.eBreakpointEventTypeInvalidType: 'Invalid Type',<br>
>     lldb.eBreakpointEventTypeLocationsAdded: 'Location Added',<br>
>     lldb.eBreakpointEventTypeLocationsRemoved: 'Location Removed',<br>
>     lldb.eBreakpointEventTypeLocationsResolved: 'Location Resolved',<br>
>     lldb.eBreakpointEventTypeRemoved: 'Removed',<br>
>     lldb.eBreakpointEventTypeThreadChanged: 'Thread Changed',<br>
> }<br>
><br>
> process_state_name_map = {<br>
>     lldb.eStateRunning: 'Running',<br>
>     lldb.eStateStepping: 'Stepping',<br>
>     lldb.eStateAttaching: 'Attaching',<br>
>     lldb.eStateConnected: 'Connected',<br>
>     lldb.eStateCrashed: 'Crashed',<br>
>     lldb.eStateDetached: 'Detached',<br>
>     lldb.eStateExited: 'Exited',<br>
>     lldb.eStateInvalid: 'Invalid',<br>
>     lldb.eStateLaunching: 'Launching',<br>
>     lldb.eStateStopped: 'Stopped',<br>
>     lldb.eStateSuspended: 'Suspended',<br>
>     lldb.eStateUnloaded: 'Unloaded',<br>
> }<br>
><br>
><br>
> class LLDBListenerThread(Thread):<br>
>     should_quit = False<br>
><br>
>     def __init__(self, debugger, running_signal=None, stopped_sigal=None):<br>
>       Thread.__init__(self)<br>
>       self._running_signal = running_signal<br>
>       self._stopped_sigal = stopped_sigal<br>
>       process = debugger.GetSelectedTarget().process<br>
>       self.listener = debugger.GetListener()<br>
>       self._add_listener_to_process(process)<br>
>       self._add_listener_to_target(process.target)<br>
><br>
>       '''self.listener.StartListeningForEventClass(debugger,<br>
> lldb.SBTarget.GetBroadcasterClassName(),<br>
>         lldb.SBTarget.eBroadcastBitBreakpointChanged |<br>
>         lldb.SBTarget.eBroadcastBitWatchpointChanged |<br>
>         lldb.SBTarget.eBroadcastBitModulesLoaded |<br>
>         lldb.SBTarget.eBroadcastBitModulesUnloaded |<br>
>         lldb.SBTarget.eBroadcastBitSymbolsLoaded)<br>
>       self.listener.StartListeningForEventClass(debugger,<br>
> lldb.SBProcess.GetBroadcasterClassName(),<br>
>         lldb.SBProcess.eBroadcastBitStateChanged |<br>
>         lldb.SBProcess.eBroadcastBitSTDOUT |<br>
>         lldb.SBProcess.eBroadcastBitSTDERR |<br>
>         lldb.SBProcess.eBroadcastBitInterrupt)'''<br>
>       '''self.listener.StartListeningForEventClass(debugger,<br>
> lldb.SBThread.GetBroadcasterClassName(),<br>
>         lldb.SBThread.eBroadcastBitStackChanged |<br>
> lldb.SBThread.eBroadcastBitThreadSuspended |<br>
>         lldb.SBThread.eBroadcastBitThreadResumed |<br>
> lldb.SBThread.eBroadcastBitSelectedFrameChanged |<br>
> lldb.SBThread.eBroadcastBitThreadSelected)'''<br>
><br>
>     def _add_listener_to_target(self, target):<br>
>         # Listen for breakpoint/watchpoint events<br>
> (Added/Removed/Disabled/etc).<br>
>         broadcaster = target.GetBroadcaster()<br>
>         mask = lldb.SBTarget.eBroadcastBitBreakpointChanged |<br>
> lldb.SBTarget.eBroadcastBitWatchpointChanged |<br>
> lldb.SBTarget.eBroadcastBitModulesLoaded<br>
>         broadcaster.AddListener(self.listener, mask)<br>
><br>
>     def _add_listener_to_process(self, process):<br>
>         # Listen for process events (Start/Stop/Interrupt/etc).<br>
>         broadcaster = process.GetBroadcaster()<br>
>         mask = lldb.SBProcess.eBroadcastBitStateChanged |<br>
> lldb.SBProcess.eBroadcastBitSTDOUT | lldb.SBProcess.eBroadcastBitSTDERR |<br>
> lldb.SBProcess.eBroadcastBitInterrupt<br>
>         broadcaster.AddListener(self.listener, mask)<br>
><br>
>     def run(self):<br>
>         print '<Listener> Listening Thread ID: %d' % thread.get_ident()<br>
>         while not self.should_quit:<br>
>             event = lldb.SBEvent()<br>
>             if self.listener.WaitForEvent(1, event):<br>
>                 if lldb.SBTarget.EventIsTargetEvent(event):<br>
>                     self._handle_target_event(event)<br>
>                 elif lldb.SBProcess.EventIsProcessEvent(event):<br>
>                     self._handle_process_event(event)<br>
>                 elif lldb.SBBreakpoint.EventIsBreakpointEvent(event):<br>
>                     self._handle_breakpoint_event(event)<br>
>                 elif lldb.SBThread.EventIsThreadEvent(event):<br>
>                     self._handle_thread_event(event)<br>
>                 else:<br>
>                     self._handle_unknown_event(event)<br>
>         print '<Listener> Exiting listener thread'<br>
><br>
>     def _handle_target_event(self, event):<br>
>         event_type = event.GetType()<br>
>         print 'Target event: %s' % target_event_type_to_name_map[event_type]<br>
><br>
>     def _handle_process_event(self, event):<br>
>         if lldb.SBProcess.GetRestartedFromEvent(event):<br>
>             print 'Non stopping event: %s' % str(event)<br>
>             return<br>
>         process = lldb.SBProcess.GetProcessFromEvent(event)<br>
>         event_type = event.GetType()<br>
>         print 'Process event: %s, %s' %<br>
> (process_event_type_to_name_map[event_type],<br>
> process_state_name_map[process.state])<br>
>         if process.state == lldb.eStateExited:<br>
>             self.should_quit = True<br>
>         elif process.state == lldb.eStateStopped:<br>
>             if self._stopped_sigal:<br>
>                 self._stopped_sigal.set()<br>
>         else:<br>
>             if self._running_signal:<br>
>                 self._running_signal.set()<br>
><br>
>         thread = process.selected_thread<br>
>         print 'Stop reason: %d' % thread.GetStopReason()<br>
>         if event_type == lldb.SBProcess.eBroadcastBitSTDOUT:<br>
>             print 'Stdout:'<br>
>             while True:<br>
>                 output = process.GetSTDOUT(1024)<br>
>                 if output is None or len(output) == 0:<br>
>                     break<br>
>                 stdout.write(output)<br>
><br>
>     def _handle_breakpoint_event(self, event):<br>
>         breakpoint = lldb.SBBreakpoint.GetBreakpointFromEvent(event)<br>
>         event_type =<br>
> lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event)<br>
>         print 'Breakpoint event: [%s] %s ' % (<br>
>             breakpoint_event_type_to_name_map[event_type],<br>
>             self._get_description_from_object(breakpoint))<br>
><br>
>     def _handle_unknown_event(self, event):<br>
>         print('Unknown event: %d %s %s' % (<br>
>             event.GetType(),<br>
>             lldb.SBEvent.GetCStringFromEvent(event),<br>
>             self._get_description_from_object(event)))<br>
><br>
>     def _get_description_from_object(self, lldb_object):<br>
>         description_stream = lldb.SBStream()<br>
>         lldb_object.GetDescription(description_stream)<br>
>         return description_stream.GetData()<br>
><br>
><br>
><br>
><br>
><br>
> On Sun, Mar 20, 2016 at 7:10 AM, Pavel Labath <<a href="mailto:labath@google.com">labath@google.com</a>> wrote:<br>
>><br>
>> If you send me a small repro case, I can try to look at why is Linux<br>
>> different here.<br>
>><br>
>> On 19 March 2016 at 00:46, Jim Ingham via lldb-dev<br>
>> <<a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a>> wrote:<br>
>> > All this logic is handled in Process::HandleProcessStateChangedEvent<br>
>> > (see around line 1215 in Process.cpp)  You shouldn’t have to reimplement the<br>
>> > logic for setting the selected thread unless you don’t like our heuristics.<br>
>> > Note, that’s in generic code, so I don’t know why it wouldn’t be working<br>
>> > right on Linux.<br>
>> ><br>
>> > Jim<br>
>> ><br>
>> >> On Mar 18, 2016, at 5:38 PM, Greg Clayton <<a href="mailto:gclayton@apple.com">gclayton@apple.com</a>> wrote:<br>
>> >><br>
>> >> It is really up to the IDE to decide this so the logic belongs in your<br>
>> >> IDE. We do things as follows:<br>
>> >><br>
>> >> If no thread was selected before, display the first thread that has a<br>
>> >> stop reason other than none. If no threads have stop reasons, select the<br>
>> >> first thread. If a thread was selected before, then see if that same thread<br>
>> >> is stopped with a reason the next time you stop and select that one,<br>
>> >> regardless if it is the first thread with a stop reason. The idea is, if you<br>
>> >> were stepping or doing something in a thread, and then stop again, you don't<br>
>> >> want the IDE changing away from your current thread if this thread has a<br>
>> >> stop reason. If this thread doesn't have a stop reason, then select the<br>
>> >> first one that does. If not threads have stop reasons, then display the same<br>
>> >> thread as before.<br>
>> >><br>
>> >>> On Mar 18, 2016, at 5:23 PM, Jeffrey Tan via lldb-dev<br>
>> >>> <<a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a>> wrote:<br>
>> >>><br>
>> >>> Thanks for the info. I understand the multiple threads stopping at the<br>
>> >>> same time issue. But I would think we should at least pick one stopped<br>
>> >>> thread and set it as selected thread instead of some random thread with stop<br>
>> >>> reason None. Also, in my repro case, there is only one thread that has stop<br>
>> >>> reason, so the heuristics should be pretty trivial to set selected thread to<br>
>> >>> that one.<br>
>> >>> I have workaround this issue with the suggestion but I think there is<br>
>> >>> a bug(on Linux) here.<br>
>> >>><br>
>> >>> On Fri, Mar 18, 2016 at 4:40 PM, Jim Ingham <<a href="mailto:jingham@apple.com">jingham@apple.com</a>> wrote:<br>
>> >>> On many platforms (OS X for sure) there’s no guarantee that when you<br>
>> >>> stop you will only have hit one breakpoint on one thread.  On OS X in<br>
>> >>> multithreaded programs, it is not at all uncommon to have many threads hit<br>
>> >>> breakpoint(s) by the the time the stop gets reported.  So you just have to<br>
>> >>> iterate over all the threads and see what their stop reasons are.  Note that<br>
>> >>> it isn’t just breakpoints, you might have been stepping on thread A, and<br>
>> >>> when you stop, thread A will have stopped with “plan complete” for the step<br>
>> >>> operation, and thread B for some other breakpoint.<br>
>> >>><br>
>> >>> So when you get a stop event you have to iterate over the threads and<br>
>> >>> see why they have stopped.<br>
>> >>><br>
>> >>> LLDB will set one of the threads as the selected thread, using some<br>
>> >>> heuristics (if you were stepping on thread A & threads A & B stopped with<br>
>> >>> breakpoints, thread A will be the selected thread, etc…)  So you could just<br>
>> >>> show the selected thread, but really you want to figure out what all the<br>
>> >>> threads are doing.<br>
>> >>><br>
>> >>> Jim<br>
>> >>><br>
>> >>>> On Mar 18, 2016, at 4:25 PM, Jeffrey Tan <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>><br>
>> >>>> wrote:<br>
>> >>>><br>
>> >>>><br>
>> >>>> Hmm, interesting, I got the stop reason from the<br>
>> >>>> lldb.SBProcess.GetProcessFromEvent(event).GetSelectedThread().GetStopReason().<br>
>> >>>> Is that thread not the one that stopped? But you are right, the breakpoint<br>
>> >>>> hits in another thread:<br>
>> >>>><br>
>> >>>> thread #87: tid = 1006769, 0x000000000042eacd<br>
>> >>>> biggrep_master_server_async`facebook::biggrep::BigGrepMasterAsync::future_find(this=0x00007f3ea2d74fd0,<br>
>> >>>> corpus=error: summary string parsing error, needle=error: summary string<br>
>> >>>> parsing error, options=0x00007f3e899fc7e0) + 51 at<br>
>> >>>> BigGrepMasterAsync.cpp:171, name = 'BigGrep-pri3-32', stop reason =<br>
>> >>>> breakpoint 1.1<br>
>> >>>><br>
>> >>>> How do I know which thread hits the breakpoint?<br>
>> >>>><br>
>> >>>> Jeffrey<br>
>> >>>><br>
>> >>>><br>
>> >>>> On Fri, Mar 18, 2016 at 4:12 PM, Jim Ingham <<a href="mailto:jingham@apple.com">jingham@apple.com</a>><br>
>> >>>> wrote:<br>
>> >>>> You only show one thread in your example.  Did another thread have a<br>
>> >>>> valid stop reason?  lldb shouldn’t be stopping for no reason anywhere…<br>
>> >>>><br>
>> >>>> Jim<br>
>> >>>><br>
>> >>>>> On Mar 18, 2016, at 4:08 PM, Jeffrey Tan via lldb-dev<br>
>> >>>>> <<a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a>> wrote:<br>
>> >>>>><br>
>> >>>>> Btw: the breakpoint I set is:<br>
>> >>>>> "b BigGrepMasterAsync.cpp:171" which is not in any of the stopped<br>
>> >>>>> stack frames.<br>
>> >>>>><br>
>> >>>>> On Fri, Mar 18, 2016 at 3:47 PM, Jeffrey Tan<br>
>> >>>>> <<a href="mailto:jeffrey.fudan@gmail.com">jeffrey.fudan@gmail.com</a>> wrote:<br>
>> >>>>> Hi,<br>
>> >>>>><br>
>> >>>>> Our IDE(wrapping lldb using python) works fine on Linux for simple<br>
>> >>>>> hello world cases. While trying a real world case, I found whenever we set a<br>
>> >>>>> source line breakpoint, then trigger the code path, lldb will send a stopped<br>
>> >>>>> state process event, with thread.GetStopReason() being None and with weird<br>
>> >>>>> callstack. Any ideas why do I get this stop stack(code is listed at the<br>
>> >>>>> end)? I have verified that if I do not set breakpoint and trigger the same<br>
>> >>>>> code path does not cause this stop event to generate.<br>
>> >>>>><br>
>> >>>>> bt<br>
>> >>>>> * thread #1: tid = 952490, 0x00007fd7cb2daa83<br>
>> >>>>> libc.so.6`__GI_epoll_wait + 51, name = 'biggrep_master_'<br>
>> >>>>>  * frame #0: 0x00007fd7cb2daa83 libc.so.6`__GI_epoll_wait + 51<br>
>> >>>>>    frame #1: 0x000000000271189f<br>
>> >>>>> biggrep_master_server_async`epoll_dispatch(base=0x00007fd7ca970800,<br>
>> >>>>> arg=0x00007fd7ca62c1e0, tv=<unavailable>) + 127 at epoll.c:315<br>
>> >>>>>    frame #2: 0x000000000270f6d1<br>
>> >>>>> biggrep_master_server_async`event_base_loop(base=0x00007fd7ca970800,<br>
>> >>>>> flags=<unavailable>) + 225 at event.c:524<br>
>> >>>>>    frame #3: 0x00000000025f9378<br>
>> >>>>> biggrep_master_server_async`folly::EventBase::loopBody(this=0x00007fd7ca945180,<br>
>> >>>>> flags=0) + 834 at EventBase.cpp:335<br>
>> >>>>>    frame #4: 0x00000000025f900b<br>
>> >>>>> biggrep_master_server_async`folly::EventBase::loop(this=0x00007fd7ca945180)<br>
>> >>>>> + 29 at EventBase.cpp:287<br>
>> >>>>>    frame #5: 0x00000000025fa053<br>
>> >>>>> biggrep_master_server_async`folly::EventBase::loopForever(this=0x00007fd7ca945180)<br>
>> >>>>> + 109 at EventBase.cpp:435<br>
>> >>>>>    frame #6: 0x0000000001e24b72<br>
>> >>>>> biggrep_master_server_async`apache::thrift::ThriftServer::serve(this=0x00007fd7ca96d710)<br>
>> >>>>> + 110 at ThriftServer.cpp:365<br>
>> >>>>>    frame #7: 0x00000000004906bc<br>
>> >>>>> biggrep_master_server_async`facebook::services::ServiceFramework::startFramework(this=0x00007ffc06776140,<br>
>> >>>>> waitUntilStop=true) + 1942 at ServiceFramework.cpp:885<br>
>> >>>>>    frame #8: 0x000000000048fe6d<br>
>> >>>>> biggrep_master_server_async`facebook::services::ServiceFramework::go(this=0x00007ffc06776140,<br>
>> >>>>> waitUntilStop=true) + 35 at ServiceFramework.cpp:775<br>
>> >>>>>    frame #9: 0x00000000004219a7<br>
>> >>>>> biggrep_master_server_async`main(argc=1, argv=0x00007ffc067769d8) + 2306 at<br>
>> >>>>> BigGrepMasterServerAsync.cpp:134<br>
>> >>>>>    frame #10: 0x00007fd7cb1ed0f6 libc.so.6`__libc_start_main + 246<br>
>> >>>>>    frame #11: 0x0000000000420bfc biggrep_master_server_async`_start<br>
>> >>>>> + 41 at start.S:122<br>
>> >>>>><br>
>> >>>>> Here is the code snippet of handling code:<br>
>> >>>>> def _handle_process_event(self, event):<br>
>> >>>>>        # Ignore non-stopping events.<br>
>> >>>>>        if lldb.SBProcess.GetRestartedFromEvent(event):<br>
>> >>>>>            log_debug('Non stopping event: %s' % str(event))<br>
>> >>>>>            return<br>
>> >>>>><br>
>> >>>>>        process = lldb.SBProcess.GetProcessFromEvent(event)<br>
>> >>>>>        if process.state == lldb.eStateStopped:<br>
>> >>>>>            self._send_paused_notification(process)<br>
>> >>>>>        elif process.state == lldb.eStateExited:<br>
>> >>>>>            exit_message = 'Process(%d) exited with: %u' % (<br>
>> >>>>>                    process.GetProcessID(),<br>
>> >>>>>                    process.GetExitStatus())<br>
>> >>>>>            if process.GetExitDescription():<br>
>> >>>>>                exit_message += (', ' + process.GetExitDescription())<br>
>> >>>>>            self._send_user_output('log', exit_message)<br>
>> >>>>>            self.should_quit = True<br>
>> >>>>>        else:<br>
>> >>>>>            self._send_notification('Debugger.resumed', None)<br>
>> >>>>><br>
>> >>>>>        event_type = event.GetType()<br>
>> >>>>>        if event_type == lldb.SBProcess.eBroadcastBitSTDOUT:<br>
>> >>>>>            # Read stdout from inferior.<br>
>> >>>>>            process_output = ''<br>
>> >>>>>            while True:<br>
>> >>>>>                output_part = process.GetSTDOUT(1024)<br>
>> >>>>>                if not output_part or len(output_part) == 0:<br>
>> >>>>>                    break<br>
>> >>>>>                process_output += output_part<br>
>> >>>>>            self._send_user_output('log', process_output)<br>
>> >>>>><br>
>> >>>>> _______________________________________________<br>
>> >>>>> lldb-dev mailing list<br>
>> >>>>> <a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a><br>
>> >>>>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev</a><br>
>> >>>><br>
>> >>>><br>
>> >>><br>
>> >>><br>
>> >>> _______________________________________________<br>
>> >>> lldb-dev mailing list<br>
>> >>> <a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a><br>
>> >>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev</a><br>
>> >><br>
>> ><br>
>> > _______________________________________________<br>
>> > lldb-dev mailing list<br>
>> > <a href="mailto:lldb-dev@lists.llvm.org">lldb-dev@lists.llvm.org</a><br>
>> > <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev</a><br>
><br>
><br>
</div></div></blockquote></div><br></div>