[LINUX] Ich möchte nur ein Signal vom Sub-Thread zum Haupt-Thread senden

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) {
    //Stopps während der Produktion und Verarbeitung der Eltern
    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;
        }
    }
    //Sammle 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 ~]#

Führen Sie pthread_self () im Hauptthread aus, bevor Sie einen Thread erzeugen Sie können es speichern.

Wenn Sie den Haupt-Thread auf der Neben-Thread-Seite benachrichtigen möchten, pthread_kill(main_pthread_t, SIGUSR1); Sie können es so benachrichtigen.

Nachdem Sie den Handler im Voraus für signalbezogene Einstellungen eingestellt haben Wenn Sie es nicht blockieren, funktioniert es nicht.

Verwenden Sie zum Zeitpunkt der Erstellung eines Threads so oft wie möglich Sigwait usw. Verhindern Sie, dass der Handler funktioniert. (Am Ende des Programms schläft der Subthread also nur im Schlaf. Diese werden nicht durch Interrupt-Verarbeitung entfernt, warten Sie auf die Anzahl der verstrichenen Sekunden und beenden Sie dann)

Wenn Sie den Code vorerst zum Laufen bringen, wird er etwas lang ... Hmm.

Nachtrag vom 10.12.2015

Als ich die Operation beobachtete, als ich ein Signal an den Haupt-Thread sendete, Andere Threads erhalten ebenfalls ...

Nur der Haupt-Thread muss das Signal mit Sigwait abfangen. Wenn andere Threads mit Sigwait warten, Sowohl der Haupt-Thread als auch andere Threads werden von sigwait zurückgegeben ...

Hmmm, Subthread-> Entscheide das Signal, das separat an den Haupt-Thread gesendet werden soll. Dies ist eine Lösung, wenn Sie nicht auf das Signal auf der Subthread-Seite warten. ..

Ich frage mich, ob es schlauer ist und ich kein Signal nur an den Haupt-Thread senden kann.

Ich habe den Hauptthread pthread_t gespeichert, um ein Signal mit pthread_kill zu senden. Immerhin scheint es gleichbedeutend mit dem Prozess des Killens zu sein (pid des Hauptthreads, SIGUSR1);

Hmm.

Recommended Posts

Ich möchte nur ein Signal vom Sub-Thread zum Haupt-Thread senden
[LINE Messaging API] Ich möchte eine Nachricht vom Programm an alle LINE senden
Ich möchte eine Nachricht von Python an LINE Bot senden
Ich möchte den Dateinamen von DataLoader sehen
Ich möchte automatisch eine Unternehmensgründungs-E-Mail senden
Senden Sie ein Signal an den Unterprozess
[Python] Ich habe ein System erstellt, um "das Rezept, das ich wirklich will" von der Rezeptseite einzuführen!
Ich möchte viele Prozesse von Python aus starten
Ich möchte nur die SudachiPy-Normalisierungsverarbeitung verwenden
Ich möchte die zulässige Ausfallzeit aus der Betriebsrate berechnen
Ich möchte das Paket aus den Anforderungen.txt mit Poesie installieren
Ich möchte vorerst eine Docker-Datei erstellen.
Ich möchte mit Python nur das Gesicht aus einem Personenbild ausschneiden und speichern ~ Gesichtserkennung und Zuschneiden mit face_recognition ~
Ich möchte die Ausführungszeit aufzeichnen und ein Protokoll führen.
Ich möchte automatisch hochwertige Teile aus den von mir aufgenommenen Videos finden
Ich möchte ein System erstellen, um zu verhindern, dass vergessen wird, den Schlüssel 1 festzuziehen
Ich möchte eine Parameterliste aus CloudFormation-Code (yaml) erstellen.
Ich habe versucht, ein Standbild aus dem Video auszuschneiden
Ich möchte Informationen von fstab am ssh-Verbindungsziel abrufen und den Befehl ausführen
Ich möchte Spyder an die Taskleiste anheften
Ich möchte kühl auf die Konsole ausgeben
Ich möchte in der Einschlussnotation drucken
Ich möchte mit dem Reim Teil1 umgehen
Ich möchte mit dem Reim part3 umgehen
Ich möchte ein Glas aus Python verwenden
Ich möchte eine Python-Umgebung erstellen
Ich möchte den Fortschrittsbalken anzeigen
Ich möchte mit dem Reim part2 umgehen
Ich möchte mit dem Reim part5 umgehen
Ich möchte mit dem Reim part4 umgehen
[Python-Memo] Ich möchte eine zweistellige Hexadezimalzahl aus einer Dezimalzahl erhalten
Ich möchte eine Liste in der Reihenfolge anderer Listen sortieren
Ich habe versucht, mit django eine E-Mail zum Abschluss der Registrierung von Google Mail zu senden.
Python: Ich möchte die Verarbeitungszeit einer Funktion genau messen
Ich möchte Affenpatches nur teilweise sicher mit Python machen
Ich möchte nur den Befehl SMTP MAIL FROM und den Befehl RCPT TO verwenden, ohne E-Mails mit Pythons smtplib zu senden
Ich möchte Matplotlib zu einem dunklen Thema machen
Senden Sie eine Nachricht von Slack an einen Python-Server
Ich möchte aus verschiedenen Sprachen eine Verbindung zu PostgreSQL herstellen
Ich möchte einfach ein Rauschmodell erstellen
[Ansible] Ich möchte meine eigene Funktion über das Vorlagenmodul (Makro) aufrufen.
Ich möchte nur verschiedene Zeilen der Textdatei mit diff anzeigen
Ich möchte einen DataFrame in MSSQL einfügen
Die Geschichte der IPv6-Adresse, die ich auf ein Minimum beschränken möchte
Ich möchte mit Python ein Fenster erstellen
Ich möchte mit Python eine E-Mail von Google Mail senden.
[Python] Ich möchte 7DaysToDie von Discord aus verwalten! 1/3
Ich möchte ein Spiel mit Python machen
Ich möchte mit dem Reim part7 (BOW) umgehen
Ich möchte gleichzeitig einen Musik-Player erstellen und Musik ablegen
Ich möchte keinen Codierungstest machen
Ich möchte einen Lebenszyklus in der Aufgabendefinition von ECS festlegen
Verwenden Sie PIL in Python, um nur die gewünschten Daten aus Exif zu extrahieren
Ich möchte Passungen aus meinem Kopf machen
Ich möchte dem Anfang einer WAV-Datei 1 Sekunde lang Stille hinzufügen
Ich möchte eine Liste der WebDAV-Dateien im Modul Anfragen anzeigen
Ich möchte Ceres Solver aus Python verwenden
Ich habe ein Tool zum Generieren von Markdown aus der exportierten Scrapbox-JSON-Datei erstellt