2017-05-10 3 views
-1

Ich habe ein Programm, das erstellt std::thread Objekte verwendet, um die Arbeit gleichzeitig auszuführen. Ich rufe das Programm von einem Bash-Skript auf und möchte das Skript stoppen, wenn das Programm nicht mit EXIT_SUCCESS beendet wird. Ich habe in der folgenden Situation ein eher nicht intuitives Verhalten festgestellt: Einer der Threads löst eine Ausnahme aus (und ruft so std::terminate auf), was zu einem vollständigen Programmabschluss führt. Der Rückkehrcode des Programms ist jedoch EXIT_SUCCESS (anstelle eines Fehlercodes, den ich erwarten würde). Warum das?C++ - Programm-Rückgabecode, wenn std :: terminate im Thread aufgerufen wird

Ich weiß, dass die Verwendung von std::thread in vielen Fällen keine clevere Idee ist und ich plane, zu std::async (oder ähnlichem) zu wechseln, aber im Moment bin ich an einer schnellen Lösung interessiert.

+0

Es ist Ihr Programm. Sie haben die vollständige Kontrolle über den Exit-Status. – stark

+1

Können Sie MCVE anzeigen? – Jarod42

+0

Es sollte dies tun ('std :: terminate' ruft' std :: abort' auf): _ "Implementierter definierter Status wird an die Host-Umgebung zurückgegeben, der eine nicht erfolgreiche Ausführung anzeigt." _ Wir benötigen [mcve] + Plattform-Details. siehe: http://en.cppreference.com/w/cpp/utility/program/abort –

Antwort

1

Nun, halte mich für dumm. Das Programm gibt korrekt einen Fehlercode zurück, aber während ich die Ausgabe (es schreibt viel log) in tee übertrug, ist der in $? gespeicherte Rückkehrcode wahrscheinlich der von tee, der ohne Fehler beendet wird.

[EDIT] Ich verwende jetzt, um den richtigen Exit-Code zu erhalten.

+0

Betrachte dich stattdessen als intelligent :) Du hast die wahre Ursache des Problems herausgefunden, indem du genau untersucht hast, was du getan hast. –

1

Wie Richard Critten im Kommentar std::terminate() auf Anrufe std::abort() hingewiesen hat, aber das ist nicht alles.

C++ bietet einige Mechanismen, um solche Situationen zu kontrollieren. Die, die ich vorschlagen kann, ist die folgende:

für Anrufe von std::terminate() Ihren eigenen Handler registrieren die mit std::set_terminate():

#include <iostream> 
#include <cstdlib> 
#include <exception> 

int main() 
{ 
    std::set_terminate 
    ([]() 
     { 
     std::cout << "Unhandled exception\n"; 
     std::exit(EXIT_FAILURE); 
     } 
    ); 

    throw 1; 
} 

Aufruf std::exit() verursacht normalen Programmabbruch mit einigen Bereinigungsschritte.

Eine andere Alternative wäre, den SIGABORT Handler zu registrieren und das Programm mit dem gewünschten Beendigungscode zu beenden. Aber in diesem Fall wird keine Ressourcenbereinigung durchgeführt.

0

C++ 11 hat den exception_ptr Typ, der es ermöglicht, Ausnahmen zwischen Threads zu transportieren. In dem Fall, wenn Sie Ausnahmen behandeln möchten, können Sie den folgenden Ansatz betrachten.

#include <iostream> 
#include<thread> 
#include<exception> 
#include<stdexcept> 

static std::exception_ptr eptr = nullptr; 

void foo() 
{ 
    try 
    { 
     .... 
     throw std::runtime_error("Bla bla"); // put your exception instead of runtime_error 
    } 
    catch(...) 
    { 
     eptr = std::current_exception(); 
    } 
} 

int main(int argc, char **argv) 
{ 
    std::thread t(foo); 
    t.join(); 

    if (eptr) 
    { 
     try 
     { 
      std::rethrow_exception(eptr); 
     } 
     catch(const std::exception &ex) 
     { 
      std::cerr << "Thread exited: " << ex.what() << "\n"; 
      return EXIT_FAILURE; 

     } 
    } 

    return EXIT_SUCCESS; 
} 

Diese Methode stellt sicher, dass das Programm mit dem Status EXIT_FAILURE verlassen wird, wenn der Thread eine Ausnahme auslöst.

Verwandte Themen