zoukankan      html  css  js  c++  java
  • 多线程----信号处理

    1,在linux的信号机制里面,有很多信号的默认处理都是结束进程,例如SIGPIPE,SIGINT

    如果我们没有对信号进行处理,那么我们的程序就不太健壮。

    2,不同的操作系统,多线程中对信号的处理不一致。

    linux的线程其实就是一个轻量级的进程,每一个线程都可以接收和处理信号。

    例如,linux中信号处理默认是由主线程进行,但如果主线程对某个信号进行了屏蔽,这个信号就可以交给其它可以处理的线程进行处理。

    3,为了统一,我们可以在主线程里面接收和处理信号,而其它线程屏蔽所有信号。

    代码如下:

    rbsignal.h

    #ifndef _RB_SIGNAL_H
    #define _RB_SIGNAL_H
    #include <sys/signal.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/socket.h>
    
    void set_pipe(int p);
    
    //阻塞所有的信号
    void block_all_signal();
    
    
    //主线程信号处理
    void main_thread_sig_hand();
    
    //信号是否在信号掩码中
    int is_member(int sig);
    
    #endif
    

    rbsignal.cc

    #include "rbsignal.h" 
    
    static int rb_pipe;
    void set_pipe(int p)
    {
        rb_pipe = p;
    }
    
    //阻塞所有的信号
    void block_all_signal()
    {
        sigset_t mask;
        sigfillset(&mask);
        int rc = pthread_sigmask(SIG_BLOCK, &mask, NULL);
        if (rc != 0)
        {
            fprintf(stderr, "block all signal error: %s
    ", strerror(rc));
            exit;
        }
    }
    
    //所有信号的处理函数
    //就是向管道发一个信号值,以便在libevent循环中处理,目标:统一事件源
    static void sig_handler(int sig)
    {
        int save_errno = errno;
        int msg = sig;
        int r = write(rb_pipe, (char*)&msg, 4);
        errno = save_errno;
    }
    
    //安装一个信号处理程序
    static void add_signal(int sig)
    {
       struct sigaction action;
       memset(&action, 0, sizeof(action));
       action.sa_handler = sig_handler;
       sigfillset(&action.sa_mask);
       sigaction(sig, &action, NULL);
    }
    
    //主线程的信号处理
    void main_thread_sig_hand()
    {
            sigset_t except;
            sigemptyset(&except);
            sigaddset(&except, SIGHUP);
            sigaddset(&except, SIGPIPE);
            sigaddset(&except, SIGTERM);
            sigaddset(&except, SIGINT);
        int rc= pthread_sigmask(SIG_UNBLOCK, &except, NULL);
        if (rc != 0)
        {
            fprintf(stderr, "main thread signal error: %s
    ", strerror(rc));
            exit;
        }      
        add_signal(SIGHUP);
        add_signal(SIGPIPE);
        add_signal(SIGTERM);
        add_signal(SIGINT);
    }
    //信号是否在信号掩码中
    int is_member(int sig)
    {
        sigset_t old;
        pthread_sigmask(SIG_SETMASK, NULL, &old);
        return sigismember(&old, sig);
    }

    以上两个文件是信号处理模块的相关接口,使用方法如下:

    /*信号处理---在主线程生成多线程前阻塞所有信号,这样在子线程中可以继承主线程的信号处理,即阻塞所有信号*/
        block_all_signal();
    
    /*初始化线程池*/
        thread_pool_init(thread_num);
    /*为主线程添加信号处理---子线程生成完成后,再由主线程接收对信号的处理*/
      int pipefd[2];
    pipe(pipefd); set_pipe(pipefd[1]); main_thread_sig_hand();
    //在libevent统一的事件处理中,对信号进行处理
    //......
    event_set(&sig_event,pipefd[0], EV_READ|EV_PERSIST, sig_callback, NULL);
    //......

    void sig_callback(int fd,short ev,void *arg) { char c[4]; read(fd, c ,4); int sig = *(int*)c; switch(sig) { case SIGHUP: fprintf(stderr,"receive SIGHUP "); break; case SIGINT: fprintf(stderr,"receive SIGINT "); break; case SIGTERM: fprintf(stderr,"receive SIGTERM "); break; case SIGPIPE: fprintf(stderr,"receive SIGPIPE "); break; } }

    代码可以下载:https://github.com/hxdoit/real_time_rank/tree/master/server1-1.0  (整个服务端)

    https://github.com/hxdoit/real_time_rank/blob/master/server1-1.0/rbsignal.h  (信号相关的部分)

    https://github.com/hxdoit/real_time_rank/blob/master/server1-1.0/rbsignal.cc (信号相关的部分)

    https://github.com/hxdoit/real_time_rank/blob/master/server1-1.0/server.cc (信号相关的部分)

  • 相关阅读:
    passwd: Have exhausted maximum number of retries for service
    将单个文件上传到多机器工具
    leetcode-Jump game II
    LeetCode--Combination Sum --ZZ
    Leetcode- Find Minimum in Rotated Sorted Array-ZZ
    leetcode-permutation sequence
    leetcode-next permutation
    LeetCode-Subsets ZZ
    leetcode-Restore IP Addresses-ZZ
    leetcode-palindrome partitioning-ZZ
  • 原文地址:https://www.cnblogs.com/hxdoit/p/3475193.html
Copyright © 2011-2022 走看看