Thread Signal

Feature

  • 每個 thread 都有自己的 signal mask
  • signal disposition 是每個 thread 共享的
  • signal 只會被 deliver 給 process 中的一個 thread

Table

How the signal was generatedWhat generated the signalEffective target of the signalHow the signal-processing thread is selected
SynchronouslyThe system, because of an exceptionA specific threadAlways the offended thread
SynchronouslyAn internal thread using pthread_killA specific threadAlways the targeted thread
AsynchronouslyAn external process using killThe process as a wholePer-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;
}