web-dev-qa-db-fra.com

Comment puis-je tuer un processus qui est mort mais en écoutant?

Je développe une application qui écoute le port 3000. Apparemment, le port écoute toujours car, à chaque démarrage, il ne peut pas créer d'écouteur (C #, TcpListener, mais ce n'est pas pertinent) car le port est déjà pris.

L'application n'existe pas dans le gestionnaire de tâches. J'ai donc essayé de trouver son PID et de le tuer, ce qui a conduit à ce résultat intéressant:

C:\Users\username>netstat -o -n -a | findstr 0.0:3000
   TCP    0.0.0.0:3000           0.0.0.0:0              LISTENING       3116

C:\Users\username>taskkill /F /PID 3116
ERROR: The process "3116" not found.

Je n'avais jamais vu ce comportement auparavant et pensais que c'était assez intéressant pour voir si quelqu'un avait une solution.

UPDATE: J'ai démarré Process Explorer et fait une recherche sur 3000 et constaté ceci:

<Non-existent Process>(3000): 5552

J'ai fait un clic droit dessus et choisi "Fermer le manche". Ce n'est plus dans Process Explorer, mais apparaît toujours dans netstat et empêche toujours l'application de démarrer l'écouteur.

UPDATE 2: Trouvé TCPView pour Windows qui affiche le processus sous la forme "<non-existent>". Comme avec CurrPorts, rien ne se passe lorsque j'essaie de fermer la connexion dans cet outil.

45
Srekel

Pour éviter des attentes interminables sur le socket, votre programme doit utiliser la fonction de setsockopt avec les paramètres SO_REUSEADDR et SO_RCVTIMEO:

SO_REUSEADDR : Allows the socket to be bound to an address that is already in use.
SO_RCVTIMEO : Sets the timeout, in milliseconds, for blocking receive calls. 
13
harrymc

Nous avions le même problème et utilisions Process Explorer de Microsoft Sysinternals pour rechercher l'ID de processus qui n'existait plus.

Il s'avère que le processus a été référencé par plusieurs processus DrWatson. Tuer ces processus a libéré le port. DrWatson est utilisé pour envoyer des vidages de mémoire à Microsoft, ce qui prenait plusieurs heures, car le processus à l'origine du plantage contenait plusieurs dizaines de Go de mémoire à la fois.

12
David

Le problème probable est que votre processus a démarré un autre processus (enfant) qui a hérité du descripteur de socket et qu'il est toujours en cours d'exécution.

Il existe différents moyens d'éviter ce problème, par exemple: ProcessStartInfo.UseShellExecute = true;

7
Nick Westgate

Je pense que vous devriez essayer CurrPorts

CurrPorts est un logiciel de surveillance réseau qui affiche la liste de tous les ports TCP/IP et UDP actuellement ouverts sur votre ordinateur local. Pour chaque port de la liste, des informations sur le processus qui a ouvert le port sont également affichées, y compris le nom du processus, le chemin complet du processus, les informations de version du processus (nom du produit, description du fichier, etc.), l'heure à laquelle le processus a été créé et l'utilisateur qui l'a créé.

De plus, CurrPorts vous permet de fermer les connexions non désirées TCP, de tuer le processus qui a ouvert les ports et d'enregistrer les informations sur les ports TCP/UDP dans des fichiers HTML, XML ou Fichier texte délimité par des tabulations.

CurrPorts marque également automatiquement en rose les ports TCP/UDP suspects appartenant à des applications non identifiées (Applications sans informations de version et icônes)

alt text

7
Sathyajith Bhat

Il faut mentionner le terme persister ici.

Les détails peuvent être trouvés à http://msdn.Microsoft.com/en-us/library/ms739165.aspx

En bref: Une option indique au système de socket de garder un socket ouvert même après sa fermeture si des données non envoyées sont présentes.

Dans votre application C #, vous pouvez spécifier les options connexes via Socket.SetSocketOption: http://msdn.Microsoft.com/en-us/library/1011kecd.aspx

Puisque tout ce qui est mentionné concerne l'envoi et les clients, mais que nous avions des problèmes similaires au travail, certaines recherches ultérieures ont révélé qu'il était possible de spécifier l'option de linger pour les écouteurs, comme le montre l'exemple ci-dessous: http://msdn.Microsoft.com/library/system.net.sockets.tcplistener.server.aspx

Certains collègues ont parlé des ports détenus par le système d'exploitation après une fermeture/fermeture d'application pendant environ deux minutes. Cela étant, il serait intéressant de savoir si le port est toujours tenu après un certain temps.

1
Andreas

J'ai eu le même problème et résolu par:

  • trouver le PID avec netstat -o
  • Tuez-le avec processus xp

Il est intéressant de noter que netstat peut parfois renvoyer un pid mais pas le nom de l'exécutable correspondant!

1
eka808

Pouvez-vous voir le processus dans Process Explorer? Si oui que vous pouvez le tuer à partir de là, mais seulement après avoir enquêté sur ce que c'est réellement (vous pouvez voir toutes les dll chargées dans le processus)

1
Jakub Konecki

Je rencontre aussi ce problème. Finalement j'ai trouvé ma raison. C'est causé par le processus principal appelé un processus enfant par popen dans c/c ++. Mais le processus principal se bloque/se ferme avant d'appeler pclose. Ensuite, le port traitera le processus principal toujours actif et l'écoutera toujours.

1
lorry.lee

nous avons rencontré un problème similaire lorsque la cause première était la création d’un processus enfant héritant des ports, le processus parent était bloqué, alors que le processus enfant détenait toujours le port. La solution consistait à identifier le processus enfant toujours en cours d'exécution et à l'arrêter. Dans l'exemple ci-dessous, le PID de processus non existant était 7336

> wmic process get processid,parentprocessid | findstr/i 7336
7336             23828

Pour arrêter ce processus:

> taskkill /f /pid 23828

Et cela a résolu le problème.

1
Michael

J'ai eu le même problème avec xdebug, il a laissé le port 9000 ouvert.

J'ai réussi à fermer avec cmd en utilisant "taskkill/pid xxxx".

Le pid du processus utilisant le port peut être récupéré avec "netstat -o".

Ma configuration était win 7 home premium.

1
Christoforos

Essayez de lancer un drapeau '-b' sur votre commande netstat. Il vous dira le nom de l'exécutable qui utilise le port. Puis trouvez ce proc dans le gestionnaire de tâches et tuez-le là. Si cela ne fonctionne pas, affichez l'exécutable qui maintient le port ouvert.

1
Ge3ng

Le problème peut être causé si le processus mort a démarré un ou plusieurs processus enfants. Si

BOOL WINAPI CreateProcess(
_In_opt_    LPCTSTR               lpApplicationName,
_Inout_opt_ LPTSTR                lpCommandLine,
_In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
_In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_        BOOL                  bInheritHandles,
_In_        DWORD                 dwCreationFlags,
_In_opt_    LPVOID                lpEnvironment,
_In_opt_    LPCTSTR               lpCurrentDirectory,
_In_        LPSTARTUPINFO         lpStartupInfo,
_Out_       LPPROCESS_INFORMATION lpProcessInformation
);

a été utilisé pour démarrer un processus enfant, cela dépend de la valeur des handles hérités, donc avec

bInheritHandles = false 

Windows ne bloquera pas le port si le processus parent est arrêté et que le processus client est toujours en cours d'exécution.

1
V15I0N

Je ne suppose pas que vous avez un pare-feu installé (ou essayé de tweeks réseau Windows)?

Certains pare-feu présentent ce type de comportement et peuvent maintenir les ports ouverts.

Si vous en avez un, essayez de le désactiver, puis lancez votre programme et fermez-le pour voir ce qui se passe.

0
William Hilsum

J'ai eu le même problème. Le processus était en cours de débogage alors qu'il se bloquait et il y avait toujours un processus vsjitdebugger.exe en attente suspendu qui faisait apparemment référence au processus en cours de débogage. Tuer ce processus vsjitdebugger.exe a résolu le problème.

0
gpvos

Étant donné que votre processus est répertorié en tant que système, vous pouvez probablement le supprimer à l'invite de commande "Système". Le compte système a plus de privilèges qu'un administrateur ordinaire.

Vous pouvez obtenir un cmd.exe "System" en planifiant une tâche pour cmd.exe (le planificateur s'exécute en tant que système):

at 15:23 /interactive "cmd.exe" 

Changer ce moment pour quelque chose dans un proche avenir. Assurez-vous également que vous êtes sur la console de l'ordinateur (si vous êtes sur une session de serveur Terminal Server normale, vous ne verrez pas le nouveau cmd.exe. Créez une connexion mstsc à la console). Je suppose qu'il existe d'autres moyens de le faire, mais cela a fonctionné pour moi dans le passé.

0
David Suarez

Une utilisation hybride de TCPView et de Process Explorer a fonctionné pour moi;) J'ai d'abord cherché l'identificateur de processus qui utilisait le port dans TCPView. Isolé le processus dans Process Explorer et tué le processus à l'aide de Process Explorer.

0
Sathiya Narayanan