2010-09-27 23 views
3

Je développe une DLL en C++ qui doit écrire des données via une connexion TCP/IP (précédemment établie) en utilisant l'appel write(). Pour être précis, la DLL doit envoyer un petit message «Processus 12345 se termine à 2007-09-27 15:30:42, la valeur de i est 131» sur le fil lorsque le processus tombe en panne. Malheureusement, tous les moyens que je connais pour détecter la fin du processus sont apparemment trop tard pour que les appels réseau réussissent. En particulier, j'ai essayé les approches suivantes et l'appel write() retourné -1 dans tous les cas:Comment puis-je effectuer des E/S réseau à la fin de la vie d'un processus?

  1. Appel write() du destructor d'un objet global.
  2. Appel de write() à partir d'une fonction de rappel enregistrée en utilisant atexit().
  3. Appel write() à partir de DllMain (dans le cas où l'argument reason est DLL_PROCESS_DETACH). Je sais que ce n'est pas une chose sûre, mais je suis un peu désespéré. :-)

Je suis conscient qu'une DLL ne peut pas détecter tout arrêt de processus (il aurait été déchargé longtemps avant que le processus se termine) mais étant donné que les données d'arrêt que la DLL doit envoyer dépend autre code dans la DLL, c'est acceptable. Je suis fondamentalement à la recherche du dernier moment où je peux effectuer en toute sécurité des réseaux d'E/S.

Est-ce que quelqu'un sait comment faire cela?

Répondre

3

Envisager de surveiller le processus à partir d'un processus de surveillance distinct.

Déterminer si un processus est désengagée: http://msdn.microsoft.com/en-us/library/y111seb2(v=VS.71).aspx

Tutoriel: Gérer un processus Windows: http://msdn.microsoft.com/en-us/library/s9tkk4a3(v=VS.71).aspx

+0

L'utilisation d'un processus de surveillance est une bonne idée. Je vais y réfléchir un peu. Malheureusement, les pages que vos liens pointent à parler seulement de la gestion des processus de processus étrangers (pas l'actuel). –

0

Je suggère de prendre l'option 3. Il suffit de faire votre chargement/déchargement de la DLL correctement et tout va bien. Appel write()devrait de travail, je ne peux pas expliquer pourquoi ce n'est pas dans votre cas. Est-il possible que l'appel échoue pour une raison différente qui n'est pas liée?

Cela fonctionne-t-il si vous appelez votre fonction DLL manuellement à partir de l'application hôte?

+1

http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx documente un certain nombre de choses qui ne devraient pas être faites (ou qui sont destinées à échouer) à partir de 'DllMain'. En effet, lorsque Windows arrête un processus, les DLL peuvent être déchargées dans n'importe quel ordre, ce qui peut être le cas lorsque 'Ws2_32.dll' a été déchargé avant votre DLL. – rwong

+0

Si je lis correctement la documentation de 'DllMain', seules certaines fonctions de' kernel32.dll' (celles qui ne chargent pas d'autres DLL) peuvent être appelées depuis 'DllMain'. –

+0

@ user198397 - le problème avec cette approche est qu'il n'y a aucune garantie que WInsock n'a pas déjà été arrêté et/ou détaché du processus. L'ordre de libération des DLL n'est pas contrôlé par OP. @frerich doit d'abord identifier un point fiable auquel faire ses appels socket. –

0

Pourquoi? Fermez la prise. Si c'est la seule fin dans le programme, ce qui, selon votre description, doit l'être, indique à l'autre extrémité que cette fin est en cours et vous pouvez envoyer les informations d'ID de processus au début et non à la fin. Vous ne devriez rien faire de chronophage ou potentiellement bloquer dans un hook de sortie ou un destructeur statique.

+0

Vous avez raison. Cependant, j'étais malheureusement un peu imprécis: j'ai besoin d'enregistrer un peu plus d'informations que juste le PID. J'ai étendu ma question en conséquence. –

0

Où Winsock est-il arrêté à l'aide de WSACleanup? Vous devez vous assurer que vos E/S sont terminées avant que cela se produise.

Vous devriez être en mesure de travailler si cela se produit en plaçant un point d'arrêt sur l'appel Win32 dans Winsock2.dll. Le déchargement des DLL est affiché dans la sortie de la fenêtre de débogage.

+0

J'ai vérifié qu'au moins aucun code * my * n'appelle WSACleanup() avant l'appel write(). Mon soupçon est qu'un autre code (peut-être dans une autre DLL qui est déchargée avant que ma propre DLL ne soit déchargée) détruit toute l'API socket avant que je puisse vider mes données. Peut-être que la DLL WinSock elle-même est déchargée avant d'être déchargée, je ne sais pas. –

+0

@Frerich - voir modifier –

2

Envisagez d'utiliser Windows Job Objects.

Votre programme principal (programme de surveillance, qui utilisera par exemple send()) peut démarrer le processus fils suspendu, le placer dans un Job, puis le reprendre.Ensuite, il sera exécuté dans l'objet du travail. Vous pouvez enregistrer une notification via SetInformationJobObject avec JobObjectAssociateCompletionPortInformation. Ensuite, vous serez averti si dans le travail sera créé un processus enfant et si un processus à l'intérieur du travail sera terminé. Donc, vous serez en mesure d'envoyer tout ce dont vous avez besoin du processus de surveillance. Si vous déboguez un programme dans Visual Studio, il utilise également des objets de travail pour contrôler votre processus et tous les processus enfants que vous démarrez. J'utilise avec succès la technique en C++ et en C#. Donc, si vous avez un problème avec la mise en œuvre, je pourrais vous envoyer un exemple de code.