光是 signal 或是只有 thread 就夠複雜了, 把他們混在一起更是剪不斷、理還亂; 若再加上 fork 就更精彩了。
Pthreads programming chapter 5 (
中文版) 寫的非常清楚, 讓我們知道當 signal 加入了 thread 時, 程式員會遇到的困難, 若你的程式有奇怪的現象, 很有可能是遇上這些麻煩。當然 thread 麻煩的問題很多, 也可能是其他的問題。
當一個 signal 來的時候, 你知道是哪個 thread 被暫停下來處理這個 signal 嗎?
有時候可能是 thread 1 處理, 有時候可能是 thread 2 處理, 而你確定不管用哪個 thread 處理, 程式都能正確執行嗎? 也許你有自信, 但事實上可能和你想的不一樣。
在我的案例上, 會造成程式無法正常的結束, 程式可以結束, 但不是正常結束, 這帶來了一點小問題。
有好幾種方法可以處理這樣的情形, 可以指定某個 signal 讓某個 thread 處理, 不過要對 signal 和 thread 有
進階的理解, 可能會花點腦力, 還要有一本好書。man pthread_sigmask 有一個好例子 (th.c 是我從 man 上抄來可以 compile 的完整程式) 可以說明這件事情。這只是其中一種方法。
這個方法是先把 signal SIGUSR1, SIGTERM 擋下來 (其實就是先 queue 起來), 不讓 signal handle 立刻出動, 讓 sig_thread 這個 thread 呼叫 sigwait 取出被擋下來的 SIGUSR1 或是 SIGTERM, 然後由 sig_thread 這個 thread 處理。
我測試了兩個平台:
- mips linux 2.6.36
- Debian x86 3.14.15-2
在 mips linux 2.6.36 平台, 一個 thread 會有不同的 pid。
compile command:
mipsel-linux-gcc th.c -o th -pthread
# pid: 19316
sig thread pid: 19318
ps
19316 root 60 S ./th
19317 root 60 S ./th
19318 root 60 S ./th
x86:
compile command:
gcc th.c -o th -pthread
不同 thread 有相同的 pid, 這是我預期的。
descent@debianlinux:tmp$ pid: 10902
sig thread pid: 10902
man pthreads 可以得到進一步資訊, linux 上有實作兩種 POSIX threads: NPTL, LinuxThreads。
LinuxThreads:
Threads do not share process IDs.
所以我的疑惑解除了。
還有別的方法, 不過由於這個就搞定我的問題了, 所以只能分享這個方法。最後我得遺憾的告訴你, Pthreads Programming 的中文版絕版了。
Hi Descent
回覆刪除按照您的說法
那段範例的寫法 只能使用在x86平台嗎?
另外假如是遇到
Program terminated with signal 4, Illegal instruction.
您覺得擋得住嗎@@?
sigaddset (&set, SIGILL);
回覆刪除descent@debian-vm:progs$ kill -ILL %2
descent@debian-vm:progs$ Signal handling thread got signal 4
我增加了 SIGILL, 看來沒問題。
在 x86/mips 都可以正常執行, arm 平台我沒測試過。