1. 程式人生 > >gdb的多執行緒除錯

gdb的多執行緒除錯

一些術語
all-stop mode 全停模式
single-stepping 單步執行
scheduler-locking 排程鎖
schedule-multiple 多程序排程
record mode 記錄模式
replay mode 回放模式

inferior
GDB用 inferior 來表示每個程式執行,inferior 與程序對應,也可用於沒有程序的target。
Inferiors在程序執行之前建立,在程序退出之後保留。Inferior 也有自己的標記,這個標記與PID不同。
通常,每個inferior都有自己的不同地址空間,一些嵌入式 targets 可以在一個地址空間的不同部分執行不同的 inferior。
每個 inferior 內可以有多個執行緒執行。

(gdb) info threads
(gdb) thread n
(gdb) set scheduler-locking [off|on|step]
(gdb) set schedule-multiple [off|on]
(gdb) show scheduler-locking
(gdb) show schedule-multiple

在開始之前先說一些技巧吧:
1 如果你在程式沒執行前想設定 scheduler-locking 的狀態,總是給出如下的提示:
Target 'exec' cannot support this command.
那你可以先在 main 函式處打個斷點,gdb main ,等待執行後停在斷點處,再執行你的設定。
其實可以在任何斷點停住的地方進行設定。

2 線上程的程式碼裡設定了斷點,那遇到斷點所有的執行緒都會停止。且自動切換到斷點所線上程。
info threads 列出的執行緒列表裡,當前執行緒前邊有個 * 號。


5.5.1 All-Stop Mode

In all-stop mode, whenever your program stops under GDB for any reason, all threads of execution
stop, not just the current thread. This allows you to examine the overall state of the program,
including switching between threads, without worrying that things may change underfoot.

在全停模式下,當你的程式由於任何原因在 GDB 下停止時,不止當前的執行緒停止,所有的執行執行緒都停止。這樣允許你檢查程
序的整體狀態,包括執行緒之間的切換,不用擔心當下會有什麼改變。

Conversely, whenever you restart the program, all threads start executing. This is true even when
single-stepping with commands like step or next.

相反,重啟程式,所有的執行緒開始執行。即時使用像 step 或者 next 這樣的單步命令,也是如此。

In particular, GDB cannot single-step all threads in lockstep. Since thread scheduling is up to
your debugging target’s operating system (not controlled by GDB), other threads may execute more
than one statement while the current thread completes a single step. Moreover, in general other
threads stop in the middle of a statement, rather than at a clean statement boundary, when the
program stops.

特別是,GDB 不能步調一致的單步執行所有執行緒。因為執行緒排程是作業系統負責的,當前執行緒完成一個單步額同時其它執行緒可能執行了
多個語句。此外,程式停止時,通常其它執行緒停止在語句的中間,而不是在一個清晰的語句邊界,

You might even find your program stopped in another thread after continuing or even single-stepping.
This happens whenever some other thread runs into a breakpoint, a signal, or an exception before
the first thread completes whatever you requested.

執行繼續或者單步後,你甚至可能發現程式在另一個執行緒中停止了,這個停止發生在第一個執行緒完成你的請求的任何操作之前(括號內為
個人理解,比如你請求了一個斷點,就是說斷點停住的時候所有執行緒已經停止了),每當有其它執行緒執行到一個斷點,訊號,或者特例。

Whenever GDB stops your program, due to a breakpoint or a signal, it automatically selects the
thread where that breakpoint or signal happened. GDB alerts you to the context switch with a
message such as ‘[Switching to Thread n]’ to identify the thread.

每當 GDB 停止程式,處理斷點或者訊號,它自動選擇斷點或者訊號發生的執行緒。GDB 通過 “[Switching to Thread n]” 之類的
訊息提醒上下文的切換,以標識執行緒。

On some OSes, you can modify GDB’s default behavior by locking the OS scheduler to allow only a
single thread to run.

在一些作業系統,可以通過鎖定系統排程而只允許一個執行緒執行的方法修改 GDB 的預設習慣。

set scheduler-locking mode
Set the scheduler locking mode. It applies to normal execution, record mode, and replay mode. If it
is off, then there is no locking and any thread may run at any time. If on, then only the current
thread may run when the inferior is resumed. The step mode optimizes for single-stepping; it
prevents other threads from preempting the current thread while you are stepping, so that the focus
of debugging does not change unexpectedly. Other threads never get a chance to run when you step,
and they are completely free to run when you use commands like ‘continue’, ‘until’, or ‘finish’.
However, unless another thread hits a breakpoint during its timeslice, GDB does not change the
current thread away from the thread that you are debugging. The replay mode behaves like off in
record mode and like on in replay mode.

設定排程鎖模式。應用於正常執行,記錄模式和回放模式。如果是 off ,那麼不鎖定,任何執行緒可在任何時間執行(但是一旦遇到斷點,
所有的執行緒都會停住)。如果是 on ,僅當前執行緒在 inferior 被恢復(就是斷點繼續)時執行。step 模式優化單步執行;執行單步
除錯時防止其它執行緒搶佔當前執行緒,以便除錯的焦點不會意外改變。執行單步(next或step)時其它執行緒沒有機會執行,執行continue,
until, 或者 finish 後執行緒被完全釋放執行。但是,除非另一個執行緒在時間片內擊中斷點,GDB 不離開當前正在除錯的執行緒。回放
模式在記錄模式下表現的像關閉,在回放模式下表現的像開啟。

show scheduler-locking
Display the current scheduler locking mode.

顯示當前的排程鎖模式。

By default, when you issue one of the execution commands such as continue, next or step, GDB allows
only threads of the current inferior to run. For example, if GDB is attached to two inferiors, each
with two threads, the continue command resumes only the two threads of the current inferior. This
is useful, for example, when you debug a program that forks and you want to hold the parent stopped
(so that, for instance, it doesn’t run to exit), while you debug the child. In other situations,
you may not be interested in inspecting the current state of any of the processes GDB is attached
to, and you may want to resume them all until some breakpoint is hit. In the latter case, you can
instruct GDB to allow all threads of all the inferiors to run with the set schedule-multiple
command.

預設情況下,當你發出一個執行命令,如 continue, next, 或 step,GDB 僅允許當前 inferior 的執行緒執行。比如,如果 GDB
被依附到兩個 inferior,每個有2個執行緒,continue 僅恢復當前 inferior 的2個執行緒。這是有用的,比如,除錯鉤子程式,想停
止父程序(比如讓它不執行就退出)當你除錯子程序時。在其它情況下,你可能對被GDB依附的程式的當前狀態不感興趣,你可能想恢復所
有的程序,直到斷點被擊中。最後一種情況,你可以使用 set schedule-multiple 命令,指示 GDB 允許所有 inferior 的所有
執行緒執行。

set schedule-multiple
Set the mode for allowing threads of multiple processes to be resumed when an execution command is
issued. When on, all threads of all processes are allowed to run. When off, only the threads of the
current process are resumed. The default is off. The scheduler-locking mode takes precedence when
set to on, or while you are stepping and set to step.

設定當執行命令時(是否)允許多個程序的執行緒被恢復的模式。如果是 on ,所有程序的執行緒被允許執行。如果是 off ,僅當前程序的
執行緒被恢復。預設值是 off 。 scheduler-locking 模式設定為 on 時, 或者設定為 step 並且正在執行單步除錯,這時
scheduler-locking 優先。

show schedule-multiple
Display the current mode for resuming the execution of threads of multiple processes.
顯示用於恢復多程序執行緒執行的當前模式。