7
votes

TerminerProcess VS Ctrl + C

J'ai un programme en mode console qui utilise SQLite3 pour maintenir un fichier de base de données. Il faut un certain temps pour exécuter, mais il devrait être en sécurité à tout moment d'annuler, en supposant que la base de données écrit se produise. (Tout est sous Windows)

est-il plus sûr, du point d'un programme en cours d'exécution, de frapper Ctrl kbd> C kbd> dans la console que d'avoir un autre appel de programme Terminez-vous à ce sujet? P>

J'ai remarqué que je peux obtenir une corruption de base de données si la traduction est appelée, je suppose que cela est parce que le programme n'a pas la possibilité de terminer les écrivies. Je suppose que ctrl kbd> C kbd> est meilleur, car le programme obtient un signal et se termine plutôt que le système d'exploitation qui le tue. P>

Notez que le Le programme ne gère pas réellement le signal (sauf si SQLite ne le fait); Je parle des mécanismes de défaut intégrés des exécutables Win32 pour gérer le signal CTRL KBD> C kbd>. P>

Pour clarifier / simplifier la question donnée que cette écriture vient d'être exécutée: p>

fwrite(buf, 1024*1024, 1, stream);


0 commentaires

4 Réponses :


1
votes

SQLite prétend être atomique, même pendant les défaillances de puissance, voir http://www.sqlite.org /atomiccommit.html .

La seule exception à ceci est que certains systèmes de disque signaleront que l'écriture s'est produite avec succès avant que les données ne soient réellement écrites sur les plateaux de disques, c'est-à-dire dans le cache de disque ou que le système d'exploitation est couché à SQLite. Voir http://www.sqlite.org/Lockingv3.html , Section 6.0 Comment corrompre vos fichiers de base de données.

processus qui sont terminés DOIVENT arrêter tous les threads d'exécution et compléter les opérations d'E / S en attente avant de quitter . L'intégrité des données devrait être assurée, à condition que le processus ne s'est pas écrasé.


2 commentaires

"La seule différence à cet égard entre une CTRL-C et une traduction traiteur est la manière dont la demande a été écrite pour gérer l'un de ces événements". Est-ce que cette conjecture ou avez-vous une preuve de la sauvegarde?


Le lien que Manuel a donné semble être faisant autorité. Apparemment, j'ai fait une hypothèse incorrecte sur la fin; Il doit être en attente d'E / S qui détient la tâche ouverte, plutôt que le programmeur interceptant l'appel terminé. J'ai édité ma réponse pour le refléter.



1
votes

Votre application a la possibilité de gérer Ctrl C et ctrl pause , comme des coups de clés ou des signaux (dépend de la configuration), ce qui signifie que l'application a la possibilité de faire une sortie propre, celles-ci seraient un moyen beaucoup plus doux de mettre fin à un processus, ce qui lui permettrait un peu plus de temps d'exécution si rien d'autre.

TerminerProcess est plus un coup de pied dans les dents, l'application ne peut pas gérer cela, il provient du noyau et si l'application pourrait le gérer, cela créerait toutes sortes de problèmes avec les processus «Unes tuerables» suspendus à leur gestionnaire de traitement de ligne et refuser de sortir.

Si je comprends bien dès que la procédure est appelée sur le processus, il ne peut pas exécuter plus de code c'est-à-dire, pas de nettoyage, aucun arrêt, il ne pouvait tout simplement pas gérer si Vous pourriez, pas d'une perspective de sécurité.

Article de projet d'excellent code ici sur la manipulation des signaux de console Windows:

http://www.codeproject.com/kb/winsdk/console_event_handling.aspx

Mise en œuvre de la manipulation du signal ci-dessus Vous pouvez vous assurer que la base de données écrit avoir une chance de terminer avant la sortie du programme, plutôt que de le laisser au hasard.

Vous pouvez bloquer une programmation à résilier, mais sa programmation «Pas vraiment« poli », c'est plus comme une programmation de kit de racine, j'ai vu un bon article à ce sujet sur rootkit.com alors recherchez-la pour« Processus Invinbility »une fois que vous avez invincible Processus, il pourrait à son époque, arrêtez-vous après avoir reçu une telle «demande» et effectuer un nettoyage avant HNAD, mais cela le plus certainement un piratage.

Il me semble que le comportement CTRL C que vous voyez actuellement est due à la fin du processus d'exécution.


0 commentaires

0
votes

Je crois que pour vos besoins, il est plus sûr d'utiliser CTRL C . Cela entraînera une interruption d'un signal envoyé au programme. Si le programme ne gère pas le signal, il se terminera sur place.

TerminaisonProcesses termine de force le processus et les filets enfants.

de MSDN :

Terminer la fonctionProcess se termine le processus spécifié et tout son fils. ... Remarques

La fonction TerminerProcess est utilisée de manière inconditionnelle, causer un processus de sortir. L'état des données globales Maintenu par des bibliothèques dynamiques de liaison (DLL) peut être compromis si La traduction est utilisée plutôt que ExitProcess.

TerminerProcess initie la résiliation et retourne immédiatement. Cela arrête Exécution de tous les fils dans le processus et demande d'annulation de tous en attente d'E / S. La résiliation processus ne peut pas quitter jusqu'à ce que tous en attente Les E / S ont été complétées ou annulées.

Un processus ne peut pas s'empêcher de être terminé.

Il existe des moyens pour qu'un processus de blocage de la traduction, mais je doute que SQLite3 le fera.


2 commentaires

Votre article semble indiquer qu'il n'y a pas de différence, mais vous dites qu'il est plus sûr d'utiliser CTRL + C. N'oubliez pas que nous parlons d'un programme non spécifiquement écrit pour gérer les signaux. Y a-t-il une raison pour laquelle vous dites qu'il est plus sûr d'utiliser CTRL + C?


CTRL + C ne forcerait pas la résiliation du processus et des fils d'enfants, il ne le dirait que d'arrêter. Si ce n'est pas manipulé, alors il quitte juste. La traduction de la traduction peut causer une corruption de données mondiale comme indiqué sur MSDN. Dans votre solution, vous déclarez que rien ne cesserait l'écriture; C'est parce que même la traduction de la propriété ne finira pas qu'il n'y a pas d'E / S («le processus terminé ne peut quitter que tous les E / S en attente sont terminés ou annulés.»). C'était aussi dans MSDN.



6
votes

Tous sont des arguments convaincants, mais le seul moyen de savoir avec certitude est de l'essayer. J'ai donc écrit un programme simple qui alloue un tampon de 1 Go, attribue quelques données à celui-ci, puis l'écrit à un fichier à l'aide d'un seul FC (). J'ai essayé plusieurs méthodes pour obtenir l'écriture sur "corrompue" les données (je m'attendais à un fichier tronqué, spécifiquement):

  • appeler TerminerProcess (via la fonction de kill de Perl et Win32 :: processus :: tuer)
  • frapper ctrl c
  • Utilisation du "processus final" de la tâche
  • Utilisation de "TuR Process" de Process Explorer

    Rien ne ferait arrêter l'écriture dans tous les cas, le fichier était la bonne taille et avait les données correctes. Et bien que le "tuer" se produise instantanément, le processus s'attarderait jusqu'à ce que l'écriture soit terminée.

    Il semble concluant qu'il n'y a pas de différence entre TerminerProcess et CTRL C à partir d'un point de vue d'E / S - une fois que l'écriture commence, il semble garantis de compléter ( sauf des pannes de courant).


2 commentaires

Très intéressant, je suppose que l'opération de l'OI se termine sans distinction, car il n'a tout simplement pas de sens de l'arrêter, de quoi pourrait-il faire autre chose que de conduire à la corruption. Doit être une autre façon de bloquer la traduction de la traduction cachée quelque part. Choses intéressantes. Merci.


Je soupçonne que la traduction ne peut pas tuer le processus en toute sécurité alors qu'il effectue un syscall: le contexte de thread à ce stade est dans l'espace du noyau et le tuant de force là-bas peut étancher des ressources système. Le système d'exploitation installe probablement des crochets pour tous les threads du processus exécutant actuellement dans l'espace du noyau qui tue le fil lorsqu'il essaie de revenir du Syscall.