[lldb] Will the rest of threads pause if `ni` execute after `thread select`? Does `lldb` support controlling one thread at a time by default?

Hi,
I’m reading program control section of lldb (Tutorial - 🐛 LLDB), and it seems the program control commands (c, si, ni, until) execute in one thread by default.

Does this mean the rest of threads will pause in the default lldb mode? This is what I’m looking for, but want to ask since it requires an explicit set-up called “set scheduler-locking on” or non-stop mode in gdb (linux - How to continue one thread at a time when debugging a multithreaded program in GDB? - Stack Overflow), in case I miss anything.

Relatedly, if lldb allows controlling exactly one thread, does it mean users of debugger need to coordinate all the threads if there are locks involved in the program? Or is there an option to allow all threads to execute if users of debugger type “next” or “continue”?


Update:

Does this mean the rest of threads will pause in the default lldb mode?

By an exercise it seems to be the case for ni at least. But it’d be great if I could get some help on

  1. the general practices when users need to coordinate a bunch of threads when locks are involved.
  2. the rationales / thoughts of choosing a different default from gdb, and how I may switch between
    a) executing exactly one thread
    and
    b) stop if any thread encounters a breakpoint (which is the gdb default)
1 Like

lldb will attempt to run only the thread on which you are stepping if it can determine that is safe against deadlocks. Otherwise it will let all threads run so that users don’t have to manually unblock from deadlocks.

Since lldb has no way to know what goes on under a function call, by default, lldb will run all threads whenever it steps over a function call. It also does that when running from a cross-library trampoline to the target, and a few other less common operations. Since ni steps over function calls, it will sometimes cause all threads to run. si is the only stepping operation that will run only the thread on which it is issued. So by default, users with multiple threads & locks should not have to manually intervene, but might see more than one thread run.

It’s been years since I’ve worked on gdb, but I am pretty sure this is what gdb used to do when scheduler-locking was set to step(?). This seems the most useful behavior. Having to interrupt a step then go find thread with the lock & manually step it out past the lock is pretty annoying. And if you aren’t aware of all the locks the system is taking for you, would be totally confusing.

You can change the default behavior of stepping using the --run-mode option which is available in all the stepping commands. If you set it to this-thread it will only run the current thread, but that may cause that thread to stall waiting for locks.

I’m not sure what you mean by question 2b. lldb always stops if any thread encounters a breakpoint, but that has little to do with the stepping modes - except of course for the fact that if you don’t let a thread run, it’s not going to hit any breakpoints.

1 Like

I see. The first few instructions doesn’t involve any function calls, so that might explain why ni allows one thread to proceed in this particular case; and last week when I combined a few breakpoints and continue, a couple of threads indeed all made progress.

You can change the default behavior of stepping using the --run-mode option which is available in all the stepping commands. If you set it to this-thread it will only run the current thread, but that may cause that thread to stall waiting for locks.

Ack, got it!

I’m not sure what you mean by question 2b. lldb always stops if any thread encounters a breakpoint, but that has little to do with the stepping modes.

I was actually looking for the --run-mode option. Thanks!