Poignée CTRL+C sur Win32
J'ai quelques problèmes avec le traitement de CTRL+C événements, dans un Win32 en C++ programme de console.
Fondamentalement, mon programme ressemble à ceci: (basé sur cette autre question: Windows Ctrl-C - Nettoyage des locaux de la pile des objets dans l'application en ligne de commande)
bool running;
int main() {
running = true;
SetConsoleCtrlHandler((PHANDLER_ROUTINE) consoleHandler, TRUE);
while (running) {
//do work
...
}
//do cleanup
...
return 0;
}
bool consoleHandler(int signal) {
if (signal == CTRL_C_EVENT) {
running = false;
}
return true;
}
Le problème est le nettoyage de code qui n'est pas exécutée du tout.
Après l'exécution de la fonction de gestionnaire le processus est terminé, mais sans exécuter le code après la boucle principale. Quel est le problème?
EDIT: comme l'a demandé, c'est un test minimal cas semblable à celui de mon programme: http://pastebin.com/6rLK6BU2
Je ne comprends pas le "test de nettoyage-instruction" chaîne dans ma sortie.
Je ne sais pas si c'est important, je suis de la compilation avec MinGW.
EDIT 2: Le problème avec les cas de test du programme est l'utilisation de la Sleep()
fonction. Sans elle, le programme fonctionne comme prévu.
Dans Win32, le gestionnaire d'une fonction s'exécute dans un autre thread, donc lorsque le gestionnaire/thread se termine son exécution, le thread principal est de dormir. C'est probablement la cause de l'interruption du process?
SetConsoleCtrlHandler
retour?Êtes-vous sûr que le
ConsoleHandler
fonction s'exécute à tous? Si vous exécutez le programme dans le débogueur et définir un point d'arrêt, l'arrêt au point d'arrêt?Aussi, vous devez utiliser le type BOOL pour la retval, et DWORD pour l'argument de consoleHandler. Aussi, FAUX/VRAI à l'intérieur...
Et vous déclarer une fonction prototype de la
consoleHandler
fonction avant d'appeler SetConsoleCtrlHandler
?Alors comment voulez-vous vérifier que le code après la boucle ne veut pas s'exécuter? Si vous définissez un point d'arrêt à ce code et l'exécuter dans un débogueur, il va s'arrêter là?
OriginalL'auteur eang | 2013-08-17
Vous devez vous connecter pour publier un commentaire.
Le code suivant fonctionne pour moi:
OriginalL'auteur lpapp
Selon la documentation, lorsque le gestionnaire (qui est déclaré à tort, d'ailleurs) reçoit un
CTRL_CLOSE_EVENT
,CTRL_LOGOFF_EVENT
, ouCTRL_SHUTDOWN_EVENT
signal, le processus est arrêté après le gestionnaire des sorties. Pour faire ce que vous essayez, vous sont censés se déplacer à votre code de nettoyage dans le gestionnaire lui-même.CTRL_C_EVENT
. Testé tout à l'heure avec unswitch
dans mon gestionnaire de fonction, et en appuyant sur CTRL+C dans la console.OriginalL'auteur Remy Lebeau
En fonction de vos besoins spécifiques, vous avez un certain nombre d'options. Si vous voulez simplement ignorer Ctrl+C vous pouvez appeler
SetConsoleCtrlHandler
passantNULL
comme leHandlerRoutine
paramètre:Cette opération supprime tous les gestionnaires de signaux. Pour mettre fin à cette application, vous devez mettre en œuvre une logique personnalisée pour déterminer quand arrêter.
Si vous souhaitez gérer Ctrl+C vous avez deux options: mettre en place un gestionnaire pour le signal ou passer le clavier de saisie sur clavier régulier de la manipulation.
La configuration d'un gestionnaire est similaire au code ci-dessus, mais au lieu de passer
NULL
que le gestionnaire vous fournir votre propre mise en œuvre.La sortie de cette application est:
Noter que le code de nettoyage est exécuté, quel que soit le code à l'intérieur de la principale
while
en boucle. Les gestionnaires de signaux de forme d'une liste liée, où les fonctions de gestionnaire sont appelés sur une la dernière, appelée jusqu'à ce que l'un des gestionnaires d'retourneTRUE
. Si aucun des gestionnaires renvoie la valeur TRUE, le gestionnaire par défaut est appelé. Le gestionnaire par défaut pour une console appelsExitProcess
lors du traitement Ctrl+C.Si vous voulez éviter tout prétraitement et de gérer Ctrl+C comme clavier régulier de l'entrée de la place, vous devez changer le mode de console en appelant
SetConsoleMode
.Une fois le
ENABLE_PROCESSED_INPUT
drapeau est supprimé Ctrl+C n'est plus traitée par le système et transmis à la console comme régulière la saisie au clavier. Il peut être lu à l'aide deReadConsoleInput
ouReadFile
.Avertissement: Le ci-dessus a été testé sur Windows 8 64bit, compilé en 32 et 64 bits, Release et Debug configurations.
OriginalL'auteur IInspectable