2015-06-29 7 views
5

Ich verstehe, dass über die einzige Sache, die ein Signal-Handler in ISO/C++ 11 zu tun ist, ist zu lesen oder zu schreiben eine Sperre frei atomare Variable oder ein volatile sig_atomic_t (ich glaube, POSIX ist etwas permissiver und erlaubt es, eine Reihe von Systemfunktionen aufzurufen.Aufwachen Thread von Signal-Handler

Ich fragte mich, ob es einen Weg gibt, einen Thread aufzuwecken, der auf eine Zustandsvariable wartet. I.e. so etwas wie:

#include <mutex> 
#include <atomic> 
#include <condition_variable> 


std::mutex mux; 
std::condition_variable cv; 

std::atomic_bool doWait{ true }; 

void signalHandler(int){ 
    doWait = false; 
    cv.notify_one(); 
} 

int main() { 
    //register signal handler 
    //Do some stuff 

    {//wait until signal arrived 
     std::unique_lock<std::mutex> ul(mux); 
     cv.wait(ul, []{return !doWait; }); 
    } 

    //Do some more stuff 
} 

, die mindestens zwei Probleme:

  1. Ich glaube, ich bin nicht notify_one() in einem Signal-Handler aufrufen erlaubt (corrct mich, wenn ich falsch liege)
  2. Das Signal könnte genau zwischen dem Check für doWait und dem Einschlafen des Threads ankommen, also würde es niemals aufwachen (offensichtlich kann ich den Mutex im SignalHander nicht sperren, um das zu vermeiden).

Bisher war die einzige Lösung, die ich sehen kann, ist damit beschäftigt Warten auf die doWait Variable zu implementieren (wahrscheinlich für ein paar Millisekunden in jeder Iteration schlafen), die mich als recht ineffizient trifft.

Beachten Sie, dass obwohl mein Programm oben nur einen Thread hat, habe ich meine Frage mit Multithreading markiert, weil es um Thread-Steuerelement-Primitive geht. Wenn es in Standard-C++ keine Lösung gibt, wäre ich bereit, eine Lösung mit Linux/POSIX-spezifischen Funktionen zu akzeptieren.

Antwort

5

Unter der Annahme, dass Ihre Lieferanten Standardbibliothek die pthread_cond_* Funktionen verwendet implementieren C++ 11 Bedingungsvariablen (libstdC++ und libC++ dies tun), die pthread_cond_* Funktionen sind nicht Asynchron-Signal-Safe so kann nicht von einem Signal-Handler aufgerufen werden.

Von http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_cond_broadcast.html:

Es ist nicht sicher ist, die pthread_cond_signal() Funktion in einem Signal-Handler zu verwenden, die asynchron aufgerufen wird. Selbst wenn es sicher wäre, würde es immer noch einen Wettlauf zwischen dem Test des Boolean pthread_cond_wait() geben, der nicht effizient eliminiert werden konnte.

Mutexe und Zustandsvariablen sind daher nicht dazu geeignet, einen wartenden Thread durch Signalisierung von Code, der in einem Signalhandler läuft, freizugeben.

Wenn Sie Semaphoren verwenden möchten, wird sem_post als async-signalsicher bezeichnet. Ansonsten sind Ihre Möglichkeiten zur Signalbehandlung die üblichen: die klassische Self-Pipe, ein Signalhandling Thread blockiert auf sigwait/sigwaitinfo, oder plattformspezifische Einrichtungen (Linux signalfd, etc.).

+0

Danke. Das habe ich befürchtet (obwohl ich die umfassende Liste der verfügbaren Linux/Posix-Mechanismen nicht kannte). Ich hoffe wirklich, wir werden eines Tages Semaphore in den Standard bringen. – MikeMB