Ceci est un ancien article, mais je cherchais un bon moyen de le faire et je n'ai pas rencontré un.
Peut-être que cela va aider quelqu'un dans une situation similaire ..
Je fais cela sur Windows, mais peut-être il est également possible sur Mac OS X/Linux en utilisant pthread mutex nommé, bien que je ne connais pas la politique de comment ces mutex sont traités si une application est terminée, ce qui est essentiel à cette technique.
Le problème avec l'aide d'un drapeau unique est qu'il ne fonctionne pas dans la situation où il peut y avoir plusieurs instances de l'application:
- App 1 fonctionne. Définit le drapeau 'N'a pas arrêté correctement'.
- L'application 2 s'exécute. Voit qu'il ne s'est pas arrêté parce que le drapeau est positionné et pense qu'il y a eu un crash alors qu'il n'y en avait pas.
C'est un peu difficile de se déplacer et il y a probablement plusieurs façons de le faire, mais cette méthode semble fonctionner OK jusqu'à présent (sous Windows, au moins):
Créer un mutex global nommé avec un GUID/UUID nouvellement généré comme nom.
Le GUID est différent pour chaque instance de l'application, chacun aura donc un mutex nommé unique. Le GUID est écrit dans un fichier contenant une liste de GUID. Si l'application s'arrête correctement, vous supprimez le GUID du fichier et le mutex est fermé. Si l'application tombe en panne ou est terminée, le GUID n'est pas supprimé du fichier MAIS le mutex est détruit par le système d'exploitation sans que l'application ne doive le faire.
Lorsque vous démarrez l'application, vous pouvez courir à travers les GUID dans la liste et appeler OpenMutex sur eux et les mutex qui n'existent pas (GetLastError renvoie ERROR_FILE_NOT_FOUND).Tout mutex inexistant indique qu'un incident/une interruption s'est produit. Tous les GUID qui ont cette propriété peuvent être supprimés de la liste à ce stade.
Une autre chose que vous pouvez faire est de supprimer les mauvais GUID de la liste lorsque vous arrêtez correctement. Cela contourne la situation suivante:
- App 1 commence
- App 2 commence
- App 1 plante
- App 2 est arrêté avec succès
- App 3 est commencé. Lorsque App 3 est démarré, il ne devrait pas signaler qu'il y a eu un plantage, car le dernier arrêt était bon.
J'ai également implémenté une sorte de spinlock sur l'accès au fichier contenant les GUID qui continueront après une période de temporisation et ne pas ajouter l'application guid au fichier. Dans de tels cas, il est probablement préférable de laisser l'application s'exécuter de toute façon et de perdre la détection de l'accident, plutôt que de ne pas exécuter l'application du tout.
D'autres mises en garde sont à conserver sur le verrou de fichier lors de l'interrogation et la mise à jour du fichier pour éviter les conditions de course. Sur Windows, cela empêche l'utilisation des flux de fichiers stl, car vous aurez besoin de tronquer le fichier après l'avoir lu tout en conservant un accès exclusif au fichier.
Hmm? Et où pourrais-je écrire ce fichier? Êtes-vous sûr que l'application est envoyée willQuit ou de telles méthodes de notification avant qu'elle ne se bloque *? Et même si c'était le cas, est-ce que l'une de ces méthodes willQuit possède un paramètre indiquant que l'application plante ou ne plante pas? – Enchilada
Oooh, je pense que je t'ai. Vous voulez juste mettre un SuccessfulQuit dans les valeurs par défaut de l'utilisateur, qui est toujours défini sur 1 lors de la fermeture réussie, est 0 par défaut et est défini sur -1 après le lancement de l'application. Et puis, si c'est effectivement -1 au lancement, cela signifie que je dois avoir crashé. Quelque chose comme ca? – Enchilada
Oui, et la lecture/écriture du fichier dans un emplacement vous appartient. –