Thread Signal
Feature
- 每個 thread 都有自己的 signal mask
- signal disposition 是每個 thread 共享的
- signal 只會被 deliver 給 process 中的一個 thread
Table
| How the signal was generated | What generated the signal | Effective target of the signal | How the signal-processing thread is selected |
|---|---|---|---|
| Synchronously | The system, because of an exception | A specific thread | Always the offended thread |
| Synchronously | An internal thread using pthread_kill | A specific thread | Always the targeted thread |
| Asynchronously | An external process using kill | The process as a whole | Per-thread signal masks of all threads in the process |
- Asynchronously signal 如果沒有做好 signal mask 設定則會隨機選擇一個 thread 傳送 signal
pthread_sigmask
Function Prototype
int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset)Function
sigprocmask 給 thread 用的版本
sigwait
Function Prototype
int sigwait(const sigset_t *restrict set, int *restrict signop)Function
- 類似 sigsuspend
set將我們想要等待的 signal 設為 1 (跟 sigsuspend 相反)signop儲存我們 deliver 的 signal 編號- 不會執行 signal handler
實際使用方式
用 multi-thread 做 signal handling 是一種 signal handler 的替代方式,每個 thread 都負責處理一種 signal(只 unblock 一個 signal),在 while loop 中呼叫 sigwait 等待 signal 並且在等到後執行原本 signal handler 的操作
用這種方式,我們可以避免 asynchronous signal handling 因為 thread 都是平行執行的,因此我們可以不用確定 signal handler 可能造成的 race condition 之類的
void * report_stats(void *p)
{
// sigset_t sigs_to_catch;
int caught;
// Must have SIGUSR1 blocked! (This thread inherits the main thread's signal mask)
// 清空訊號集合
sigemptyset(&sigs_to_catch);
// 將 SIGUSR1 加入到要等待的訊號集合中
sigaddset(&sigs_to_catch, SIGUSR1);
for (;;) {
// 阻塞性地等待 sigs_to_catch 集合中的訊號。
// 當訊號到達時,sigwait() 會自動將該訊號暫時解除遮罩,處理後再重新遮罩。
sigwait(&sigs_to_catch, &caught);
// 鎖定 mutex,因為 display_stats() 引用了被其他執行緒修改的資料
pthread_mutex_lock(&stats_lock);
display_stats(); // References data modified by other threads
pthread_mutex_unlock(&stats_lock);
}
return NULL;
}