2017-09-29 72 views
1

我通過std::getline()stdin讀取用戶輸入,我希望能夠通過SIGINT退出程序。不幸的是,std::getline()似乎沒有喚醒任何信號。因此,按下CTRL-C RETURN後,下面的代碼纔會中止。通過信號喚醒std :: getline

#include <csignal> 
#include <string> 
#include <iostream> 

bool abort_ = false; 

void SigIntHandler(int signum) { 
    std::cout << "Received SIGINT" << std::endl; 
    abort_ = true; 
} 


int main(int argc, char *argv[]) { 
    signal(SIGINT, SigIntHandler); 

    while (!abort_) { 
    std::string line; 

    std::cout << "> "; 
    std::getline(std::cin, line); 
    if (!std::cin) 
     std::cin.clear(); 

    std::cout << line << std::endl; 
    } 
} 

這是爲什麼?除用戶輸入外,我是否有機會喚醒std::getline()?或者是否有其他方式可以從stdin中讀取,也可以對信號作出響應?

回答

1

std::getline和輸入/輸出庫通常在進程接收到信號時沒有指定的行爲。 C++庫和語言不指定任何特定的行爲。信號僅簡要地順便提到,與最顯着的是參考僅:

到函數信號的呼叫與任何所得 調用,以便安裝在信號處理程序的同步。

這和頭文件的枚舉是C++庫中對信號的引用的總和。信號是一個高度操作系統特有的功能,C++庫不包含這些功能。

這裏討論的C++庫函數和類都不是信號安全的。在所示的代碼中,信號處理程序不能對輸入流做任何事情,因爲它的內部狀態是不確定的,整個事情不是信號安全的。

這樣,來處理信號,有必要訴諸低電平特定於操作系統的調用,如open()read(),和write(),而不是使用C++的輸入/輸出庫。當然,其中一個選項是編寫您自己的std::streambuf的子類,使用低級系統調用實現其功能,並適當地處理信號。通過將流緩衝區設置爲失敗狀態(或者,模擬接收鍵,嘿,這是您的節目)並返回,您自己的實現將適當地阻止輸入和處理任何接收到的信號。

+0

雖然它不影響底層點,但C++ 11增加了可以與信號處理程序同步的函數'std :: atomic_signal_fence'。 –