2017-05-10 276 views
-1

我有一個程序創建使用std::thread對象同時執行工作。我從bash腳本調用該程序,並且如果程序沒有以EXIT_SUCCESS終止,則想要停止該腳本。在以下情況中,我遇到了一個非直觀的行爲:其中一個線程拋出異常(因此調用std::terminate),導致程序完全終止。但是,該程序的返回碼是EXIT_SUCCESS(而不是我期望的某些錯誤代碼)。這是爲什麼?在線程中調用std :: terminate時C++程序的返回碼

我知道在很多情況下使用std::thread並不是一個聰明的想法,我打算轉到std::async(或類似的),但目前,我對這個快速解決方案感興趣。

+0

這是你的程序。您可以完全控制退出狀態。 – stark

+1

你可以顯示MCVE嗎? – Jarod42

+0

它應該這樣做('std :: terminate'調用'std :: abort'):_「實現定義的狀態返回到主機環境,表示不成功執行。」_我們需要[mcve] +平臺詳細信息。請參閱:http://en.cppreference.com/w/cpp/utility/program/abort –

回答

1

好吧,考慮我愚蠢。該程序正確地返回一個錯誤代碼,但當我輸出(它寫很多日誌)到tee,存儲在$?中的返回碼可能是tee中的一個,其退出時沒有失敗。

[編輯]我現在使用PIPESTATUS來得到正確的退出代碼。

+0

考慮自己聰明,而不是:)你仔細檢查你在做什麼,找出問題的真正原因。 –

1

正如Richard Critten在評論std::terminate()中指出std::abort(),但那不是全部。

C++提供了很多機制來控制這種情況。一個我可以建議如下:

註冊自己的處理程序使用std::set_terminate()std::terminate()電話:

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

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

    throw 1; 
} 

調用std::exit()導致程序正常終止與一些清理步驟。

另一種替代方法是註冊SIGABORT處理程序並退出具有所需退出代碼的程序。但是在那種情況下,沒有完成資源清理。

0

C++ 11的exception_ptr類型允許在線程之間傳輸異常。所以在這種情況下,如果你想處理異常,你可以考慮以下方法。

#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; 
} 

這種方法可以確保該計劃將與狀態EXIT_FAILURE如果線程拋出一個異常退出。

相關問題