54 votes

Comment tuer un processus qui est mort mais qui écoute ?

Je développe une application qui écoute sur le port 3000. Apparemment, il y a une instance de cette application qui écoute toujours ce port, car à chaque fois que je la lance, elle ne peut pas créer d'écouteur (C#, TcpListener, mais ce n'est pas pertinent) parce que 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 la tuer, ce qui a donné 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'ai jamais vu ce comportement auparavant et j'ai pensé que c'était suffisamment intéressant pour voir si quelqu'un avait une solution.

MISE À JOUR : J'ai lancé l'Explorateur de processus et j'ai fait une recherche pour 3000 et j'ai trouvé ceci :

<Non-existent Process>(3000): 5552

J'ai fait un clic droit dessus et choisi "Fermer la poignée". Il n'est plus dans l'explorateur de processus, mais apparaît toujours dans netstat et empêche toujours l'application de lancer le listener.

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

14voto

harrymc Points 394411

Pour éviter les attentes interminables sur le socket, votre programme devrait utiliser la fonction fonction 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.

12voto

Sk93 Points 1162

Nous avons eu le même problème et avons utilisé Explorateur de processus de Microsoft Sysinternals pour rechercher l'ID du processus qui n'existait plus.

Il s'avère que le processus a été référencé par plusieurs processus DrWatson. En tuant ces processus, le port est libéré. DrWatson est utilisé pour envoyer des vidages de mémoire à Microsoft et cela prenait plusieurs heures car le processus qui s'est écrasé possédait plusieurs dizaines de Go de mémoire à ce moment-là.

8voto

Chirantan Points 6493

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

Il existe plusieurs façons d'éviter cela, par exemple : ProcessStartInfo.UseShellExecute = true ;

7voto

Sathyajith Bhat Points 60630

Je pense que vous devriez donner CurrPorts un essai

CurrPorts est un logiciel de surveillance du 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 sur la version du processus (nom du produit, description du fichier, etc.), l'heure de création du processus et l'utilisateur qui l'a créé.

En outre, CurrPorts vous permet de fermer les connexions TCP indésirables, de tuer le processus qui a ouvert les ports, et de sauvegarder les informations sur les ports TCP/UDP dans un fichier HTML, un fichier XML, ou un fichier texte délimité par des tabulations.

CurrPorts marque aussi automatiquement d'une couleur rose les ports TCP/UDP suspects appartenant à des applications non identifiées (applications sans informations sur la version et sans icônes).

alt text

5voto

kato2 Points 151

J'ai essayé toutes les solutions commentées ci-dessus et aucune n'a fonctionné pour moi. J'ai continué à chercher et j'ai trouvé cette réponse, qui est une combinaison du commentaire de @Michael et de ce lien. https://serverfault.com/questions/181015/how-do-you-free-up-a-port-being-held-open-by-dead-process

  1. En premier lieu, vous devez trouver le processus à l'origine du problème en utilisant le numéro de port :

    netstat -abno | findstr /i "listening"| find ":3000"
        TCP    0.0.0.0:3000           0.0.0.0:0              LISTENING       3116
  2. deuxièmement, vous devez trouver l'id du processus parent (ppid) en utilisant le code de @Michael

    wmic process get processid,parentprocessid | findstr/i 3116
        3116             23828
  3. Ensuite, vous devez trouver les identifiants des processus enfants en utilisant le code suivant

    wmic process where (ParentProcessId=23828) get Caption,ProcessId
        Caption        ProcessId
        wireguard.exe  27400
  4. Tuer tous les processus depuis les processus enfants jusqu'au processus parent

    taskkill /f /pid 27400 
    taskkill /f /pid 3116 
    taskkill /f /pid 23828

Cela a résolu le problème pour moi.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X