set scheduler-locking on可强制GDB仅运行当前线程,其余线程完全冻结;执行step/next/continue均只影响当前线程,切换线程须显式使用thread ID命令。

只让当前线程运行:set scheduler-locking on
默认情况下,GDB 执行 next、step 或 continue 时,所有线程都会同时跑 —— 这不是你“只调试某一个线程”的本意。真正起作用的是 set scheduler-locking on:它强制 GDB 只调度当前选中的线程,其余线程完全冻结。
常见错误现象:单步 thread 2 时,thread 3 的全局变量却在变(比如 p counter 发现值跳涨),说明其它线程没锁住。
-
set scheduler-locking on后,step/next/continue都只影响当前线程 - 切换线程必须用
thread <ID>显式指定,否则仍操作旧线程 - 该设置不跨会话保存,每次启动 GDB 都要重设
- 注意:如果当前线程阻塞在
pthread_cond_wait或select,on模式下它也会卡住,但其它线程不会趁机执行
为特定线程单独设断点:break ... thread <ID>
想让只有线程 5 在 foo.c:42 停下,而其它线程无视该行?用带 thread 限定的断点:
(gdb) break foo.c:42 thread 5
这样即使线程 1、3、7 也执行到同一行,GDB 不会中断它们。
- 断点编号后会标注
thread 5,用info breakpoints可确认 - 不能对已存在的断点补加
thread限定,必须删掉重设 -
thread all是反向操作:让所有线程都在该位置中断 - 若线程 ID 尚未创建(比如断点设在
pthread_create之前),该断点对后续新建线程无效
检查并切换目标线程:info threads 和 thread <ID>
不先确认线程列表就盲目 thread 3,容易切错 —— 特别是线程 ID(LWP)在每次运行中不固定。
务必先执行:
(gdb) info threads
输出类似:
3 Thread 0x7ffff7012700 (LWP 12345) 0x00007ffff7bcfced in pthread_cond_wait ()
这里的 3 是 GDB 内部线程号(稳定),LWP 12345 是系统级线程 ID(每次不同)。
- 用
thread 3切换,不是thread 12345 -
info threads必须在程序已运行(至少创建过线程)后才有输出;刚run就执行会显示空列表 - 如果线程已退出,
info threads里不再显示它,thread切换会报错Thread ID not known
需要临时放开其它线程时:用 thread apply
有时你得让线程 2 单步、同时让线程 4 执行到下一个断点 —— set scheduler-locking 太粗粒度,这时用 thread apply 精确控制:
(gdb) thread apply 2 step<br>(gdb) thread apply 4 continue
这条命令本质是“向指定线程发指令”,不改变当前线程上下文。
-
thread apply all next会让所有线程各走一步(但实际执行步数可能不一致,因调度不可控) -
thread apply 2,4,6 p local_var可批量打印多个线程的同名局部变量 - 它不依赖
scheduler-locking设置,off模式下也能用 - 慎用
thread apply all continue:若某线程立刻 hit 断点,GDB 会自动切换过去,打断你原本的调试流
最易被忽略的一点:set scheduler-locking on 能锁住线程执行,但锁不住信号 —— 如果其它线程触发了 SIGSEGV 或你手动发了 kill -SIGUSR1,GDB 仍会中断并可能切换到发信号的线程。真要隔离信号,得配合 handle SIGUSR1 nostop noprint pass 之类命令。


















