[LINUX] Je souhaite envoyer un signal uniquement du sous-thread au thread principal

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) {
    //Arrêts pendant la production et le traitement des parents
    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;
        }
    }
    //Collecter les sous-threads
    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 ~]#

Exécutez pthread_self () sur le thread principal avant de générer un thread Vous pouvez le sauvegarder.

Si vous souhaitez notifier le thread principal du côté du sous-thread, pthread_kill(main_pthread_t, SIGUSR1); Vous pouvez le notifier comme ça.

Après avoir défini le gestionnaire à l'avance pour les paramètres liés au signal Si vous ne le bloquez pas, cela ne fonctionnera pas.

Au moment de créer un fil, utilisez autant que possible sigwait etc., Empêchez le gestionnaire de travailler. (Donc, à la fin du programme, le sous-thread est juste en train de dormir, Ceux-ci ne seront pas supprimés en interrompant le traitement, attendez le nombre de secondes écoulées, puis terminez)

Si vous faites fonctionner le code pour le moment, ce sera un peu long ... Hmm.

Post-scriptum du 10/12/2015

Quand je regardais l'opération, quand j'ai envoyé un signal au fil principal, D'autres threads reçoivent également ...

Seul le thread principal a besoin de capter le signal avec sigwait, Lorsque d'autres threads attendent avec sigwait, Le thread principal et les autres threads sont renvoyés par sigwait ...

Hmmm, subthread-> décidez du signal à envoyer au thread principal séparément, C'est une solution si vous n'attendez pas le signal du côté du sous-thread. ..

Je me demande si c'est plus intelligent et je ne peux pas envoyer de signal uniquement au fil principal.

J'ai sauvegardé le thread principal pthread_t pour envoyer un signal avec pthread_kill, Après tout, cela semble être équivalent au processus de kill (pid du thread principal, SIGUSR1);.

Hmm.

Recommended Posts

Je souhaite envoyer un signal uniquement du sous-thread au thread principal
[LINE Messaging API] Je souhaite envoyer un message du programme à tout le monde LINE
Je souhaite envoyer un message de Python à LINE Bot
Je veux voir le nom de fichier de DataLoader
Je souhaite envoyer automatiquement un e-mail de création d'entreprise
Envoyer un signal au sous-processus
[Python] J'ai créé un système pour introduire "la recette que je veux vraiment" depuis le site de recettes!
Je veux démarrer beaucoup de processus à partir de python
Je souhaite utiliser uniquement le traitement de normalisation SudachiPy
Je souhaite calculer le temps d'arrêt autorisé à partir du taux de fonctionnement
Je veux installer le package de requirements.txt avec poésie
Je veux créer un Dockerfile pour le moment.
Je veux découper uniquement le visage d'une image de personne avec Python et l'enregistrer ~ Détection de visage et rognage avec face_recognition ~
Je souhaite enregistrer l'heure d'exécution et conserver un journal.
Je veux trouver automatiquement des pièces de haute qualité à partir des vidéos que j'ai tournées
Je veux créer un système pour éviter d'oublier de serrer la clé 1
Je souhaite créer une liste de paramètres à partir du code CloudFormation (yaml)
J'ai essayé de couper une image fixe de la vidéo
Je veux obtenir des informations de fstab à la destination de la connexion ssh et exécuter la commande
Je veux épingler Spyder à la barre des tâches
Je veux sortir froidement sur la console
Je veux imprimer dans la notation d'inclusion
Je veux gérer la rime part1
Je veux gérer la rime part3
Je veux utiliser jar de python
Je veux créer un environnement Python
Je veux afficher la barre de progression
Je veux gérer la rime part2
Je veux gérer la rime part5
Je veux gérer la rime part4
[Mémo Python] Je souhaite obtenir un nombre hexadécimal à 2 chiffres à partir d'un nombre décimal
Je souhaite trier une liste dans l'ordre des autres listes
J'ai essayé d'envoyer un e-mail de fin d'inscription depuis Gmail avec django.
Python: je souhaite mesurer proprement le temps de traitement d'une fonction
Je veux faire un patch monkey seulement en partie en toute sécurité avec Python
Je veux utiliser uniquement la commande SMTP MAIL FROM et la commande RCPT TO sans envoyer de courrier avec le smtplib de Python
Je veux faire de matplotlib un thème sombre
Envoyer un message de Slack à un serveur Python
Je souhaite me connecter à PostgreSQL à partir de plusieurs langues
Je souhaite créer facilement un modèle de bruit
[Ansible] Je souhaite appeler ma propre fonction à partir du module de modèle (macro)
Je souhaite afficher uniquement différentes lignes du fichier texte avec diff
Je veux INSÉRER un DataFrame dans MSSQL
L'histoire de l'adresse IPv6 que je souhaite conserver au minimum
Je veux créer une fenêtre avec Python
Je souhaite envoyer un e-mail depuis Gmail en utilisant Python.
[Python] Je veux gérer 7DaysToDie depuis Discord! 1/3
Je veux faire un jeu avec Python
Je veux gérer la rime part7 (BOW)
Je veux créer un lecteur de musique et enregistrer de la musique en même temps
Je ne veux pas passer un test de codage
Je souhaite définir un cycle de vie dans la définition de tâche d'ECS
Utilisez PIL en Python pour extraire uniquement les données souhaitées d'Exif
Je veux faire des crises de ma tête
Je veux ajouter du silence pendant 1 seconde au début d'un fichier wav
Je souhaite voir une liste de fichiers WebDAV dans le module Requêtes
Je veux utiliser le solveur ceres de python
J'ai créé un outil pour générer du Markdown à partir du fichier JSON Scrapbox exporté