2017-09-29 13 views
1

Je lis l'entrée de l'utilisateur de stdin via std::getline(), et je veux pouvoir quitter le programme par SIGINT. Malheureusement, std::getline() ne semble pas se réveiller sur aucun signal. Par conséquent, le code ci-dessous n'abandonne qu'après avoir appuyé sur CTRL-C et RETURN.Réactiver std :: getline à travers le signal

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

Pourquoi est-ce ainsi? Est-ce que j'ai une chance de me réveiller std::getline() sauf par l'utilisateur? Ou existe-t-il un autre moyen de lire stdin, qui est également sensible aux signaux?

Répondre

1

std::getline, et la bibliothèque d'entrée/sortie en général, n'a pas un comportement spécifié lorsque le processus reçoit un signal. La bibliothèque C++ et la langue ne spécifient aucun comportement particulier. Les signaux sont que brièvement mentionnés en passant, avec la référence la plus notable étant seulement:

Un appel au signal de fonction synchronise avec tout résultant invocation du gestionnaire de signaux ainsi installé.

Cela, et l'énumération du fichier d'en-tête, est la somme totale des références aux signaux dans la bibliothèque C++. Les signaux sont une fonctionnalité spécifique au système, qui n'est pas couverte par la bibliothèque C++.

Aucune des fonctions de la bibliothèque C++ et des classes discutées ici ne sont sécurisées. Dans le code affiché, le gestionnaire de signal ne peut rien faire dans le flux d'entrée, car son état interne est indéterminé et le tout n'est pas sécurisé.

Ainsi, pour traiter les signaux, il sera nécessaire de recourir à des appels spécifiques à faible système d'exploitation de niveau, comme open(), read() et write(), au lieu d'utiliser la bibliothèque d'entrée/de sortie C de. Bien sûr, l'une des options est d'écrire votre propre sous-classe de std::streambuf, en implémentant sa fonctionnalité en utilisant des appels système de bas niveau, et en gérant les signaux de manière appropriée. Votre propre implémentation bloquera de manière appropriée sur l'entrée et le traitement de tout signal reçu en définissant le tampon de flux à l'état échoué (ou, peut-être, simulant la réception d'une clé ENTER, hé, c'est votre spectacle) et le retour.

+0

Bien que cela n'affecte pas le point sous-jacent, C++ 11 a ajouté la fonction 'std :: atomic_signal_fence' qui peut être synchronisée avec les gestionnaires de signaux. –