I want to send a signal only from the sub thread to the main thread

a.cpp



#include <sys/types.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>

#include <cstdio>
#include <cstring>
#include <mutex>
#include <thread>
#include <map>
#include <random>

typedef void(*Handler_func)(int);

void sig_handler(int) {
}

int check_signal() {
    sigset_t ss;
    sigemptyset(&ss);
    sigaddset(&ss, SIGTERM);
    sigaddset(&ss, SIGUSR1);
    
    timespec ts;
    ts.tv_sec = 0;
    ts.tv_nsec = 0;
    int sig = sigtimedwait(&ss, nullptr, &ts);
    if (sig > 0) {
        return sig;
    } else {
        if (errno != EAGAIN) {
            char buf[1024];
            char *bufp = strerror_r(errno, buf, 1024);
            printf("sigtimedwait fail. %s\n", bufp);
            return -1;
        }
    }
    return 0;
}

int set_sigprocmask() {
    sigset_t newss;
    sigemptyset(&newss);
    sigaddset(&newss, SIGCHLD);
    sigaddset(&newss, SIGUSR1);
    sigaddset(&newss, SIGALRM);
    sigaddset(&newss, SIGHUP);
    sigaddset(&newss, SIGINT);
    sigaddset(&newss, SIGQUIT);
    sigaddset(&newss, SIGTERM);
    if (sigprocmask(SIG_BLOCK, &newss, nullptr)) {
        return 1;
    } else {
        return 0;
    }
}

int set_sigaction(int sig, Handler_func func) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = func;
    sigemptyset(&sa.sa_mask);
    if (sigaction(sig, &sa, nullptr)) {
        return 1;
    } else {
        return 0;
    }
}

int set_sigaction_ign(int sig) {
    struct sigaction sa;
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_handler = SIG_IGN;
    sigemptyset(&sa.sa_mask);
    if (sigaction(sig, &sa, nullptr)) {
        return 1;
    } else {
        return 0;
    }
}

int init_signal() {
    set_sigaction(SIGCHLD, &sig_handler);
    set_sigaction(SIGUSR1, &sig_handler);
    set_sigaction(SIGALRM, &sig_handler);
    set_sigaction(SIGHUP, &sig_handler);
    set_sigaction(SIGINT, &sig_handler);
    set_sigaction(SIGQUIT, &sig_handler);
    set_sigaction(SIGTERM, &sig_handler);
    set_sigaction_ign(SIGPIPE);
    if (set_sigprocmask()) {
        return 1;
    } else {
        return 0;
    }
}

class th_info {
    public:
        std::thread th;
        pthread_t main_pthread_t;
};

void thread_func(std::mutex &mtx, std::map<int, th_info> &ths, int num) {
    //Stops during parental production and processing
    mtx.lock();
    mtx.unlock();
    
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<int> wait_time(1, 10);
    
    while (!check_signal()) {
        sleep(wait_time(mt));
        printf("[%d]: send SIGUSR1.\n", num);
        mtx.lock();
        pthread_kill(ths[num].main_pthread_t, SIGUSR1);
        mtx.unlock();
    }
}

void main_thread(std::mutex &mtx, std::map<int, th_info> &ths) {
    sigset_t ss;
    sigemptyset(&ss);
    sigaddset(&ss, SIGHUP);
    sigaddset(&ss, SIGTERM);
    sigaddset(&ss, SIGINT);
    sigaddset(&ss, SIGQUIT);
    sigaddset(&ss, SIGUSR1);
    while (1) {
        int sig;
        sigwait(&ss, &sig);
        if (sig == SIGUSR1) {
            printf("recv SIGUSR1.\n");
        } else {
            printf("recv FINISH SIGNAL.\n");
            break;
        }
    }
    //Collect subthreads
    mtx.lock();
    for (auto &it : ths) {
        pthread_kill(it.second.th.native_handle(), SIGUSR1);
    }
    mtx.unlock();
    for (auto &it : ths) {
        it.second.th.join();
    }
}

void gen_thread(std::mutex &mtx, std::map<int, th_info> &ths) {
    pthread_t main_pthread_t = pthread_self();
    mtx.lock();
    for (int i = 0; i < 3; ++i) {
        std::thread th(thread_func, std::ref(mtx), std::ref(ths), i);
        ths[i].th = std::move(th);
        ths[i].main_pthread_t = main_pthread_t;
    }
    mtx.unlock();
}

int main(int, char **) {
    if (init_signal()) {
        printf("init_signal fail.\n");
        return 1;
    }
    
    std::mutex mtx;
    std::map<int, th_info> ths;
    
    gen_thread(mtx, ths);
    main_thread(mtx, ths);
    
    return 0;
}

[root@localhost ~]# g++ --std=c++11 a.cpp -lpthread
[root@localhost ~]#
[root@localhost ~]# ./a.out
[1]: send SIGUSR1.
recv SIGUSR1.
[2]: send SIGUSR1.
recv SIGUSR1.
[0]: send SIGUSR1.
recv SIGUSR1.
[1]: send SIGUSR1.
recv SIGUSR1.
[2]: send SIGUSR1.
recv SIGUSR1.
[2]: send SIGUSR1.
recv SIGUSR1.
[0]: send SIGUSR1.
recv SIGUSR1.
^Crecv FINISH SIGNAL.
[1]: send SIGUSR1.
[2]: send SIGUSR1.
[0]: send SIGUSR1.
[root@localhost ~]#

Before spawning a thread, run pthread_self () on the main thread and You can save it.

If you want to notify the main thread on the sub thread side, pthread_kill(main_pthread_t, SIGUSR1); You can notify it like this.

After setting the handler in advance for signal related settings If you don't block it, it won't work.

At the time of threading, use sigwait etc. as much as possible, Prevent the handler from working. (So, at the end of the program, the subthread is just sleeping in sleep, These will not be interrupted by interrupt processing, and will end after waiting for the number of seconds passed.)

If you make the code work for the time being, it will be somewhat long ... Hmm.

2015/12/10 postscript

Looking at the operation, when I send a signal to the main thread, Other threads are also receiving ...

Only the main thread needs to catch the signal with sigwait, When other threads are also waiting with sigwait, Both the main thread and other threads are returned from sigwait ...

Hmmm, subthread-> decide the signal to send to the main thread separately, It's a solution if you don't wait for the signal on the subthread side. ..

I wonder if it's smarter and I can't send a signal only to the main thread.

I saved the main thread pthread_t to send a signal with pthread_kill, After all, it seems to be equivalent to the process of kill (pid of the main thread, SIGUSR1) ;.

Hmm.

Recommended Posts

I want to send a signal only from the sub thread to the main thread
[LINE Messaging API] I want to send a message from the program to everyone's LINE
I want to send a message from Python to LINE Bot
I want to see the file name from DataLoader
I want to send a business start email automatically
Send a signal to subprocess
[Python] I made a system to introduce "recipes I really want" from the recipe site!
I want to start a lot of processes from python
I want to use only the normalization process of SudachiPy
I want to calculate the allowable downtime from the operating rate
I want to install a package from requirements.txt with poetry
I want to create a Dockerfile for the time being.
I want to cut out only the face from a person image with Python and save it ~ Face detection and trimming with face_recognition ~
I want to record the execution time and keep a log.
I want to automatically find high-quality parts from the videos I shot
I want to create a system to prevent forgetting to tighten the key 1
I want to make a parameter list from CloudFormation code (yaml)
I tried to cut out a still image from the video
I want to get information from fstab at the ssh connection destination and execute a command
I want to pin Spyder to the taskbar
I want to output to the console coolly
I want to print in a comprehension
I want to handle the rhyme part1
Send a message from Python to Slack
I want to handle the rhyme part3
I want to use jar from python
I want to build a Python environment
I want to display the progress bar
I want to handle the rhyme part2
I want to handle the rhyme part5
I want to handle the rhyme part4
[Python memo] I want to get a 2-digit hexadecimal number from a decimal number
I want to sort a list in the order of other lists
I want to identify the alert email. --Is that x a wildcard? ---
I tried to send a registration completion email from Gmail with django.
Python: I want to measure the processing time of a function neatly
I want to do a monkey patch only partially safely in Python
I want to use only the SMTP MAIL FROM command and RCPT TO command without sending mail with Python's smtplib
I want to make matplotlib a dark theme
Send a message from Slack to a Python server
I want to connect to PostgreSQL from various languages
I want to easily create a Noise Model
[Ansible] I want to call my own function from the template module (macro)
I want to display only different lines of a text file with diff
I want to INSERT a DataFrame into MSSQL
The story of IPv6 address that I want to keep at a minimum
I want to create a window in Python
I want to email from Gmail using Python.
[Python] I want to manage 7DaysToDie from Discord! 1/3
I want to perform SageMaker inference from PHP
I want to make a game with Python
I want to handle the rhyme part7 (BOW)
I want to make a music player and file music at the same time
I don't want to take a coding test
I want to set a life cycle in the task definition of ECS
Use PIL in Python to extract only the data you want from Exif
I want to make fits from my head
I want to add silence to the beginning of a wav file for 1 second
I want to see a list of WebDAV files in the Requests module
I want to use ceres solver from python
I made a tool to generate Markdown from the exported Scrapbox JSON file