2017-03-31 9 views
0

Considérons un programme parallèle constitué d'un nombre de threads de travail. Ces threads ont un poll -loop sur certains descripteurs de fichiers. Le programme est supposé fonctionner jusqu'à ce que ctrl-c soit atteint/le processus reçoit un SIGINT. Le programme ne devrait jamais se réveiller inutilement. J'ai conçu la combinaison suivante de sigwait, std::thread, pipe et pthread_sigmask Notez que dans l'application actuelle, il y a plus de descripteurs de fichiers, donc je n'utilise pas atomics pour fermer les threads.Utilisation de sigwait avec std :: thread et pipe

#include <thread> 
#include <iostream> 
#include <cstdlib> 
#include <csignal> 

extern "C" { 
#include <unistd.h> 
#include <fcntl.h> 
#include <pthread.h> 
#include <poll.h> 
} 

int fds[2]; 

void thread_run() { 
    struct pollfd pfd = {fds[0], POLLIN, 0}; 
    int ret = poll(&pfd, 1, -1); 
    if (ret != 1) std::terminate(); 
    if (!pfd.revents & POLLIN) std::abort(); 
} 

int main() 
{ 
    int ret = pipe(fds); 
    if (ret) std::abort(); 

    sigset_t ss; 
    sigemptyset(&ss); 
    sigaddset(&ss, SIGINT); 

    ret = pthread_sigmask(SIG_BLOCK, &ss, NULL); 
    if (ret) std::abort(); 

    std::thread t(thread_run); 

    int sig; 
    ret = sigwait(&ss, &sig); 
    if (ret) std::abort(); 

    char b = 0; 
    ret = write(fds[1], &b, 1); 
    if (ret != 1) std::abort(); 

    t.join(); 

    close(fds[0]); 
    close(fds[1]); 
} 

Le programme semble fonctionner sans problème.

  1. Cette approche est-elle conforme ou suis-je en train de négliger les mises en garde?
  2. Y a-t-il des cas d'erreur spécifiques qui peuvent survenir lors de l'opération normale et qui peuvent être gérés plus facilement?
  3. Le programme serait-il toujours correct si je permute std::thread -creation et pthread_sigmask?

Répondre

1
  1. Ceci est une approche standard recommandée et cela fonctionne bien. Voir la section des exemples dans pthread_sigmask.
  2. Impossible d'en trouver.
  3. Ce ne serait pas correct. La plupart des signaux sont spécifiques au processus, ce qui signifie qu'ils sont transmis à n'importe quel thread dans le processus qui ne bloque pas ce signal. Par conséquent, ce signal doit être bloqué dans tous les threads sauf celui qui gère le signal.

Vous pouvez utiliser std::abort appel pour des situations inattendues. std::terminateest appelée par le runtime C++ lorsque la gestion des exceptions échoue.

+0

Juste pour clarifier 3): Cela signifie-t-il qu'il y a en effet des sigmasks séparés par thread (et que pthread_sigmask' définit l'actuel), mais ils sont hérités lors de la création du thread? Merci aussi pour la remarque sur 'std :: terminate' /' std :: abort'! – Zulan

+1

Oui, chaque thread a son propre masque de signal, ils sont hérités du thread de création, voir [pthread_create] (http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_create.html). –