9
votes

Détecter la terminaison du programme (C, Windows)

J'ai un programme qui doit effectuer certaines tâches avant de finir. Le problème est que parfois le programme se bloque avec une exception (comme la base de données, etc.). Maintenant, y a-t-il un moyen de détecter une résiliation anormale et d'exécuter du code avant qu'il ne meurt?

Merci.

code est apprécié.


1 commentaires

Utilisez un gestionnaire de signal SIGSEGV. ;-)


7 Réponses :


1
votes

Si c'est uniquement Windows, vous pouvez utiliser SEH ( SETUNHEDLEXCEINCEFILTER ), ou VEH ( AddvevectoredExceptionHandler , mais ce n'est que pour XP / 2003 et UP)


4 commentaires

Je pense que cela pourrait aider. Avez-vous un échantillon d'extrait?


CODEPAD.ORG/MUAUUB25D - mais c'est le plus simple, il y a plus de gestionnaires d'accident complexes sur le net (par exemple sur CodeProject).


J'ai essayé, ça avait l'air bien mais je suis si j'ai tué le processus (à partir du chef de travail, etc.), il ne le détecte pas.


De MSDN: "Si un processus est terminé par TerminonProcess, tous les threads du processus sont terminés immédiatement sans possibilité d'exécuter un code supplémentaire. Cela signifie que le thread n'exécute pas de code dans des blocs de gestion de terminaison. En outre, aucune DLL attachée n'est notifiée. que le processus se détache. ".



2
votes

Cela dépend de ce que vous faites avec vos "exceptions". Si vous les gérez correctement et que vous quittez du programme, vous pouvez vous inscrire que la fonction s'appelle à la sortie, à l'aide de atexit () .

Cela ne fonctionnera pas en cas de réelle résiliation anormale, comme Segfault.

Je ne sais pas sur Windows, mais sur le système d'exploitation compatible POSIX, vous pouvez installer un gestionnaire de signal qui attrapera différents signaux et faire quelque chose à ce sujet. Bien sûr, vous ne pouvez pas attraper sigkill et sigstop .

API de signal fait partie de l'ANSI C depuis C89, donc probablement Windows le supporte. Voir Signal () Syscall pour plus de détails.


1 commentaires

J'utilise quelque chose de similaire pour attraper Ctrl-C et d'autres signaux de terminaison, mais je ne peux pas attraper une traduction. Si je me souviens bien, vous ne pouvez pas arrêter un SIGKILL, il en va de même pour terminer la propagation. Cela provoque juste l'application mourir.



0
votes

Désolé, pas un programmeur Windows. Mais peut-être que xxx

registre une fonction à appeler lors de la terminaison du programme.

http://msdn.microsoft.com/en-us/library/aa298513%28vs.60%29.aspx


1 commentaires

Merci mais ça ne vous aide pas vraiment. Je peux attraper une résiliation normale.



0
votes

Premièrement, bien que cela soit assez évident: vous ne pouvez jamais avoir une solution complètement robuste - une personne peut toujours simplement frapper le câble d'alimentation pour terminer votre processus. Donc, vous avez besoin d'un compromis et vous devez concevoir soigneusement les détails de ce compromis.

L'une des solutions les plus robustes consiste à mettre le code concerné dans un programme d'emballage. Le programme Wrapper invoque votre programme "réel", attend que son processus se termine, puis - à moins que votre programme "réel" ne signale spécifiquement qu'il a terminé normalement - exécute le code de nettoyage. Ceci est assez courant pour des raisons telles que des harnais de test, où le programme de test est susceptible de se bloquer ou d'abandonner ou de mourir de manière inattendue.

Cela vous donne toujours la difficulté de ce qui se passe si une personne se termine une propriété sur votre fonction wrapper, si c'est quelque chose que vous devez vous inquiéter. Si nécessaire, vous pouvez contourner cela en la configurant en tant que service sous Windows et en utilisant les fonctionnalités du système d'exploitation pour le redémarrer s'il meurt. (Cela change simplement des choses un peu; quelqu'un pourrait encore juste arrêter le service.) À ce stade, vous êtes probablement à un point où vous devez signaler une achèvement réussie par quelque chose de persévérant comme créer un fichier.


1 commentaires

Je suis d'accord avec toi. Mon principal problème consiste à effectuer une dernière action avant de mourir lors d'une décroche de ligne ou d'un autre événement imprévu. Le reste des événements est pris en charge. J'ai parlé au responsable du projet sur la conversion de l'application de surveillance à un service, mais c'est un non. Je suppose qu'il n'y a pas de moyen de faire ça ...



5
votes

Il y a Sysinternals Forum threads sur la protection contre le processus final tentatives en accrochant les internaux NT, mais ce que vous voulez vraiment, c'est un chien de garde ou un processus de pairs (approche raisonnable) ou une méthode d'interception d'événements catastrophiques (jolie DICEY).

Edit: Il y a des raisons pour lesquelles ils rendent cela difficile, mais il est possible d'intercepter ou de bloquer les tentatives de tuer votre processus. Je sais que vous essayez simplement de nettoyer avant de quitter, mais dès que quelqu'un libère un processus qui ne peut pas être tué immédiatement, quelqu'un demandera une méthode de la tuer immédiatement, et ainsi de suite. Quoi qu'il en soit, pour descendre cette route, voir le fil ci-dessus et recherchez quelques mots-clés que vous trouvez là pour plus. crochet ou filtre NtterminateProcess Nous parlons de code de noyau, de pilotes de périphériques, d'antivirus, de sécurité, de logiciels malveillants, des trucs rootkit ici. Certains livres pour aider dans cette zone sont API Native Windows NT / 2000 , Secrets Windows 2000 non documentés: Un livre de recettes de programmeur , rootkits: Subvertir le noyau Windows et, bien sûr, Windows® Internals: cinquième édition . Ce genre de choses n'est pas trop difficile à coder, mais jolie touchante pour avoir raison, et vous pouvez présenter des effets secondaires inattendus.

Peut-être Fonctions de récupération d'application et de redémarrage pourrait être utile? Soutenu par Vista et Server 2008 et plus.

ApplicationRecoverycallback Fonction de rappel Fonction de rappel définie par l'application utilisée pour enregistrer les informations d'état de données et d'application dans l'événement que l'application rencontre une exception non gérée ou devient insensible.

On utilise SETUNHEDLEXCEPRETFILTER , Discussion sociale MSDN conseille que de faire ce travail de manière fiable, de corriger cette méthode en mémoire est le seul moyen d'être convaincu que votre filtre est appelé. Conseille de placer à la place avec __try / __ sauf. Quoi qu'il en soit, il existe des échantillons de code et de discussions sur les appels de filtrage vers SetunhandleXceptionFilter dans l'article "SETUNHEDLEDEXCEPRETFILTER" et VC8 < / a>.

Aussi, voir Windows SEH revisité à Le facteur impressionnant de certains échantillons de code de addveurExceptionDharler .


5 commentaires

Merci. J'ai vu ceux-là avant. Il y a 2 problèmes, tho. 1) Je dois soutenir XP. 2) Je n'ai pas besoin de récupérer d'un crash. J'ai juste besoin d'enregistrer quelques fichiers et de fermer les connexions de base de données avant de fermer l'application (gracieusement ou avant de vous battre).


Je t'ai eu. Ajout de certaines informations et de liens vers des échantillons de code et de discussion sur Souf et Aveh.


Laissez-moi essayer ceci. Néanmoins, je ne peux pas attraper une trait d'arrêt. De ce que je vois que cela n'est pas possible


Je crois que c'est possible, juste beaucoup de travail. Au niveau du noyau, vous pouvez faire tout le plus n'importe quoi, crochet et patch le plus tout. Recherchez "Hook NttermininateProcess", etc. Je vais développer un peu mon premier paragraphe, mais gardez à l'esprit qu'ils rendent cela difficile parce qu'ils ne veulent pas une course aux armements. C'est à dire. La prochaine question que quelqu'un demandera est "Comment puis-je tuer un processus errant qui refuse de terminer immédiatement?" Nous sommes dans le pilote de périphérique, antivirus, les zones rootkit ici.


:) Je ne pensais pas que tu étais. Demandez aux autres méthodes telles que SUFF, AVEH, MANUTLERS SIGNAL, PROC WATCHDOG ou __TRY / __ Sauf travailleur pour tous les cas dont vous avez besoin? Si oui, alors c'est la voie à suivre (et s'il vous plaît signaler ce qui a fonctionné pour vous - c'est un sujet intéressant). Si vous avez besoin de plus, vous devrez utiliser certaines techniques atypiques.



9
votes

1. Win32 strong>

L'API Win32 contient un moyen de le faire via le SETUNHEDLEXCEINCEFILTER Fonction, comme suit: P>

LONG myFunc(LPEXCEPTION_POINTERS p)
{
     printf("Exception!!!\n");     
     return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
     SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&myFunc);    
     // generate an exception !
     int x = 0;
     int y = 1/x;
     return 0;
}


6 commentaires

En outre, en ce qui concerne votre commentaire sur TerminerProcess () ... La réponse simple est que vous ne pouvez rien faire après la fin de la traduction () est appelée à votre processus. Ne passez pas aller, ne collectez pas 200 $. Votre processus quitte, maintenant. Période. La fin.


Merci pour les commentaires. Le problème ne sont pas des exceptions. Le problème est de détecter un crash ou un appel à la résiliation. Exceptions que je peux gérer déjà


C'est ce que SETUNHEDLEDLEXCEINCEFILTER fait, il gère des "crash" comme des débordements de pile, un accès mémoire NULL, etc. Ce n'est pas simplement un gestionnaire d'exception dans le sens de l'essai / attraction.


Voir msdn.microsoft.com/en-us/Library/ AA363082 (vs.85) .aspx , il délimite que tous les "accidents" SEH peuvent gérer.


En outre, je pense que le nom de la fonction vous confondre. Cette fonction permet spécifiquement de manipuler des "terminaisons anormales" lorsque vous les appelez. En d'autres termes, c'est la fonction qui s'appelle lorsque votre code se bloque. Cela peut et ne traitera pas de la traduction de la traduction, cependant. Donc, comme indiqué par Piotr, il ne "tirera pas" si votre processus est résilié via la traduction, et c'est par conception. SEH est ce qui est utilisé par d'innombrables programmes pour "téléphone à la maison" en cas de crash.


Merci Coleman, votre commentaire Terminer les appelsProcesses n'était pas possible de retarder sans accrocher. La réponse que je cherchais.



0
votes

J'ai publié un article sur ddj.com sur "Débogage post mortem" il y a quelques années.

Il comprend des sources pour Windows et Unix / Linux pour détecter une résiliation anormale. Par mon expérience, un gestionnaire de fenêtres installé à l'aide de SetunhandleXceptionFilter est pas toujours appelé. Dans de nombreux cas, on l'appelle, mais je reçois assez de fichiers journaux de clients qui n'incluent pas de rapport des gestionnaires installés, où c'est une violation d'accès était la cause.

http://www.ddj.com/development-tools/185300443


0 commentaires