1. 程式人生 > >執行緒與訊號 -- pthread_sigmask() sigwait()

執行緒與訊號 -- pthread_sigmask() sigwait()

一、主執行緒傳送USR1訊號給子執行緒1  ,子執行緒中新增 訊號捕捉,子執行緒2沒有捕捉訊號,導致直接退出

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

#define handle_error_en(en, msg) \
    do {errno = en; perror(msg); exit(EXIT_FAILURE); }while(0)


static void *sig_thread1(void *arg)
{
    sigset_t *set = (sigset_t *)arg;
    int ret, sig;

    sigaddset(set, SIGUSR1);
    pthread_sigmask(SIG_SETMASK, set, NULL);
    for (;;)
    {
        // 等待被遮蔽的訊號 SIGQUIT
        printf("before sigwait1..\n");
        ret = sigwait(set, &sig);
        if (ret != 0)
            handle_error_en(ret, "thread2 sigwait");
   
        printf("Signal handling thread1 got signal %d\n", sig);
    }
}       
    
static void *sig_thread2(void *arg)
{
    sigset_t set;
    sigemptyset(&set);
    
    int ret, sig;
    
    for (;;) 
    {
        // thread2 沒有設定捕捉任何訊號,
        // 除SIGQUIT被遮蔽,其餘訊號均可導致執行緒退出
        printf("before sigwait2..\n");  
        ret = sigwait(&set, &sig);      
        if (ret != 0)                   
            handle_error_en(ret, "thread2 sigwait");
                                        
        printf("Signal handling thread2 got signal %d\n", sig);
    }                                   
}   
int main(int argc, const char *argv[])  
{
    pthread_t thread1;
    pthread_t thread2;
    sigset_t set;
    int ret; 
    
    sigemptyset(&set);
    sigaddset(&set, SIGQUIT);
    
    // SIG_BLOCK 遮蔽  SIG_UNBLOCK 解遮蔽  SIG_SETMASK 設定
    ret = pthread_sigmask(SIG_BLOCK, &set, NULL);
    if (ret!=0 )
        handle_error_en(ret, "pthread_sigmask");

    ret = pthread_create(&thread1, NULL, sig_thread1, &set);


    ret = pthread_create(&thread2, NULL, sig_thread2, NULL);

    sleep(2);
    pthread_kill(thread1, SIGUSR1);
    printf("kill thread1 SIGUSR1.\n");

    sleep(2);
    pthread_kill(thread2, SIGUSR1);
    printf("kill thread2 SIGUSR1.\n");

    pause();

    return 0;
}

 

二、 執行緒1 捕捉被遮蔽訊號,執行緒2沒有捕捉

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

#define handle_error_en(en, msg) \
    do {errno = en; perror(msg); exit(EXIT_FAILURE); }while(0)


static void *sig_thread1(void *arg)
{
    sigset_t *set = (sigset_t *)arg;
    int ret, sig;

    for (;;)
    {
        // 等待被遮蔽的訊號 SIGQUIT
        printf("before sigwait1..\n");
        ret = sigwait(set, &sig);
        if (ret != 0)
            handle_error_en(ret, "thread2 sigwait");
        
        printf("Signal handling thread1 got signal %d\n", sig);
    }
}       
    
static void *sig_thread2(void *arg)
{
    sigset_t set;
    sigemptyset(&set);
    
    int ret, sig;
    
    for (;;) 
    {
        // thread2 沒有設定捕捉任何訊號,
        // 除SIGQUIT被遮蔽,其餘訊號均可導致執行緒退出
        printf("before sigwait2..\n");  
        ret = sigwait(&set, &sig);      
        if (ret != 0)                   
            handle_error_en(ret, "thread2 sigwait");
                                        
        printf("Signal handling thread2 got signal %d\n", sig);
    }                                   
}   
int main(int argc, const char *argv[])  
{
    pthread_t thread1;
    pthread_t thread2;
    sigset_t set;
    int ret; 
    
    sigemptyset(&set);
    sigaddset(&set, SIGQUIT);
    
    // SIG_BLOCK 遮蔽  SIG_UNBLOCK 解遮蔽  SIG_SETMASK 設定
    ret = pthread_sigmask(SIG_BLOCK, &set, NULL);
    if (ret!=0 )
        handle_error_en(ret, "pthread_sigmask");

    ret = pthread_create(&thread1, NULL, sig_thread1, &set);


    ret = pthread_create(&thread2, NULL, sig_thread2, NULL);

    sleep(2);
    pthread_kill(thread1, SIGQUIT);
    printf("kill thread1 SIGQUIT.\n");

    sleep(2);
    pthread_kill(thread2, SIGQUIT);
    printf("kill thread2 SIGQUIT.\n");

    pause();

    return 0;
}