Wie kann ich einen Prozess beenden, der tot ist, aber zuhört?


48

Ich entwickle eine App, die auf Port 3000 lauscht. Anscheinend hört eine Instanz den Port immer noch ab, da sie beim Starten keinen Listener erstellen kann (C #, TcpListener, aber das ist irrelevant), da der Port bereits vorhanden ist genommen.

Da die App im Task-Manager nicht vorhanden ist, habe ich versucht, ihre PID zu finden und sie zu beenden. Dies führte zu folgendem interessanten Ergebnis:

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.

Ich habe dieses Verhalten noch nie gesehen und dachte, es sei interessant genug, um zu sehen, ob jemand eine Lösung hat.

UPDATE: Ich habe Process Explorer gestartet und nach 3000 gesucht und Folgendes gefunden:

<Non-existent Process>(3000): 5552

Ich habe mit der rechten Maustaste darauf geklickt und "Close Handle" gewählt. Es befindet sich nicht mehr im Prozess-Explorer, wird jedoch weiterhin in netstat angezeigt und verhindert, dass die App den Listener startet.

UPDATE 2: TCPView für Windows gefunden, die den Prozess als anzeigen"<non-existent>" . Wie bei CurrPorts passiert nichts, wenn ich versuche, die Verbindung in diesem Tool zu schließen.


ein bisschen Heilung der Krankheit durch Töten des Patienten, aber hört es auf, wenn Sie den Computer neu starten?
Xantec

2
Tatsächlich war es ausreichend, sich
aus-

Überprüfen Sie, ob eines der hier aufgeführten Programme hilft
Sathyajith Bhat

1
Mit der aktuellen Version von TCPView 3.05 "Close connection" aus dem Kontextmenü von <non-exsitent> process wurde die Verbindung in meinem Fall erfolgreich geschlossen und der Port freigegeben.
Ventzy Kunev

Antworten:


13

Um endlose Wartezeiten am Socket zu vermeiden, sollte Ihr Programm die Funktion setsockopt mit den Parametern SO_REUSEADDR und SO_RCVTIMEO verwenden:

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. 

1
Hat dies jemandem bei diesem speziellen Problem geholfen (Socket-Listening durch einen toten Prozess)?
Rustyx

12

Wir hatten das gleiche Problem und haben Process Explorer von Microsoft Sysinternals verwendet, um die nicht mehr vorhandene Prozess-ID zu ermitteln.

Es stellte sich heraus, dass der Prozess von mehreren DrWatson-Prozessen referenziert wurde. Durch das Beenden dieser Prozesse wurde der Port freigegeben. DrWatson wird zum Senden von Speicherabbildern an Microsoft verwendet. Dies dauerte mehrere Stunden, da der abgestürzte Prozess zu diesem Zeitpunkt mehrere zehn GB Speicher enthielt.


7

Ich denke, Sie sollten CurrPorts ausprobieren

CurrPorts ist eine Netzwerküberwachungssoftware, die eine Liste aller aktuell auf Ihrem lokalen Computer geöffneten TCP / IP- und UDP-Ports anzeigt. Für jeden Port in der Liste werden auch Informationen zu dem Prozess angezeigt, der den Port geöffnet hat, einschließlich des Prozessnamens, des vollständigen Pfads des Prozesses, der Versionsinformationen des Prozesses (Produktname, Dateibeschreibung usw.) sowie der Uhrzeit Der Prozess wurde erstellt und der Benutzer, der ihn erstellt hat.

Darüber hinaus können Sie mit CurrPorts unerwünschte TCP-Verbindungen schließen, den Prozess beenden, der die Ports geöffnet hat, und die TCP / UDP-Portinformationen in einer HTML-, XML- oder tabulatorgetrennten Textdatei speichern.

CurrPorts markieren auch verdächtige TCP / UDP-Ports, die nicht identifizierten Anwendungen gehören, automatisch mit rosa Farbe (Anwendungen ohne Versionsinformationen und Symbole)

Alt-Text


4
Es erscheint in der Liste unter dem Prozessnamen "System". Ich habe versucht, mit der rechten Maustaste auf das Element zu klicken, um das Schließen des Ports zu erzwingen, aber es passiert nichts.
Srekel

7

Das wahrscheinliche Problem ist, dass Ihr Prozess einen anderen (untergeordneten) Prozess gestartet hat, der das Socket-Handle geerbt hat und noch ausgeführt wird.

Es gibt verschiedene Möglichkeiten, dies zu verhindern, zum Beispiel: ProcessStartInfo.UseShellExecute = true;


1
Danke, das war gut. Ich habe subprocess.call(..., cwd=..., shell=True)als App-Launcher auf einem Python-Webserver angerufen , und es stellte sich heraus, dass ich all diese untergeordneten Prozesse beenden musste, um den Socket freizugeben. Das Seltsame ist, dass ich shell = True verwende. Das hat mich ewig geärgert.
Daniel F

Ich glaube nicht, dass die Verwendung einer Shell zu diesem Verhalten führt. Wenn Sie alle untergeordneten Prozesse beenden wollen , wenn die Eltern sterben, ich glaube , der richtige Weg ist , einen erstellen Job Objekt mit der JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE Flagge , fügen Sie jedes Kind Prozess mit AssignProcessToJobObject , und lassen Sie den Griff zu schließen natürlich , wenn die übergeordneten Prozess beendet.
Qris

1

Können Sie den Prozess im Prozess-Explorer sehen ? Wenn ja, können Sie es von dort aus töten, aber erst, nachdem Sie untersucht haben, was es tatsächlich ist (Sie können alle in den Prozess geladenen DLLs sehen).


1

Versuchen Sie, ein '-b'-Flag in Ihrem netstat-Befehl zu setzen. Es zeigt Ihnen den Namen der ausführbaren Datei an, die den Port verwendet. Dann finden Sie diesen Proc im Task-Manager und töten Sie ihn dort. Wenn das nicht funktioniert, wird der Port durch die ausführbare Datei offen gehalten.


Ich kann es im Moment nicht reproduzieren, aber ich bin mir ziemlich sicher, dass netstat es auch nicht geschafft hätte, da jeder andere Versuch (und jedes Tool), den Namen des Prozesses zu finden, fehlgeschlagen ist.
Srekel

1

Müssen hier den Begriff Verweilen erwähnen .

Details finden Sie unter http://msdn.microsoft.com/en-us/library/ms739165.aspx

Kurz gesagt: Es gibt eine Option, die das Socketsystem anweist, einen Socket auch nach dem Schließen offen zu halten, wenn nicht gesendete Daten vorhanden sind.

In Ihrer C # -App können Sie alle zugehörigen Optionen über Socket.SetSocketOption angeben: http://msdn.microsoft.com/en-us/library/1011kecd.aspx

Da sich alle erwähnten Dinge auf das Senden und die Clients beziehen, wir jedoch ähnliche Probleme hatten, wurde bei einigen weiteren Suchen festgestellt, dass die Verweildaueroption für Listener wie im folgenden Beispiel angegeben werden kann: http://msdn.microsoft.com /library/system.net.sockets.tcplistener.server.aspx

Einige Kollegen sprachen über Ports, die vom Betriebssystem nach dem Beenden / Schließen der Anwendung für etwa zwei Minuten gehalten werden. In Anbetracht dessen wäre es interessant zu hören, ob der Hafen nach einer gewissen Zeit noch gehalten wird.


Die Ports blieben viel länger offen (ich kann mich nicht erinnern, wie lange es gedauert hat, aber vielleicht bis zu einer Stunde, bevor ich aufgegeben und neu gestartet habe).
Srekel

Ich bin mir nicht sicher, ob die Option "Verweilen" für diesen speziellen Fall relevant ist, da sie anscheinend nur angibt, was nach einem Aufruf von CloseSocket passieren soll. Da ich die Anwendung beende, bezweifle ich, dass diese Funktion aufgerufen wird (?).
Srekel

1

Ich stoße auch auf dieses Problem. Endlich habe ich meinen Grund gefunden. Es wird durch den Hauptprozess verursacht, der in c / c ++ durch das Öffnen eines untergeordneten Prozesses aufgerufen wird. Aber der Hauptprozess stürzt ab / fährt herunter, bevor pclose aufgerufen wird. Dann wird der Port den Hauptprozess noch live behandeln und noch darauf lauschen.


1
Ich fand diese Antwort bei ServerFault hilfreich: serverfault.com/a/273727/8856
Harriv

1

Ich hatte das gleiche Problem mit xdebug, es ließ Port 9000 offen.

Ich habe es geschafft, mit cmd mit "taskkill / pid xxxx" zu schließen.

Die PID des Prozesses, der den Port verwendet, kann mit "netstat -o" abgerufen werden.

Meine Konfiguration war Win 7 Home Premium.


1

Ich hatte das gleiche Problem und habe es behoben durch:

  • Finden der PID mit netstat -o
  • Töte es mit process xp

Interessanterweise kann netstat manchmal eine pid zurückgeben, jedoch nicht den entsprechenden Namen der ausführbaren Datei!


1

Das Problem kann verursacht werden, wenn der tote Prozess einen oder mehrere untergeordnete Prozesse gestartet hat. Wenn

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
);

Wurde zum Starten eines untergeordneten Prozesses verwendet, hängt dies vom Wert der Vererbungshandles ab, also mit

bInheritHandles = false 

Windows blockiert den Port nicht, wenn der übergeordnete Prozess gestoppt ist und der Clientprozess noch ausgeführt wird.


1

Ein ähnliches Problem wurde festgestellt, als als die Hauptursache ein untergeordneter Prozess war, der die Ports erbte. Der übergeordnete Prozess stürzte ab, während der untergeordnete Prozess den Port noch hielt. Die Lösung bestand darin, den noch ausgeführten untergeordneten Prozess zu identifizieren und anzuhalten. In diesem Beispiel war die nicht vorhandene Prozess-PID 7336

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

So beenden Sie diesen Prozess:

> taskkill /f /pid 23828

Und das löste das Problem.


0

Ich nehme nicht an, dass Sie eine Firewall installiert haben (oder Windows-Netzwerkwochen ausprobiert haben)?

Einige Firewalls weisen dieses Verhalten auf und können Ports offen halten.

Wenn Sie eines haben, deaktivieren Sie es und starten Sie dann Ihr Programm, schließen Sie es und sehen Sie, was passiert.


Leider keine Option, da ich die Firewall auf meinem Computer nicht steuern kann.
Srekel

@Srekel - welche Firewall ist das? Da Sie Probleme haben, würde ich persönlich denken, dass es das ist, was die Probleme verursacht.
William Hilsum

0

Da Ihr Prozess als System aufgeführt ist, können Sie ihn höchstwahrscheinlich an einer Eingabeaufforderung "System" beenden. Das Systemkonto verfügt über mehr Berechtigungen als ein regulärer Administrator.

Sie können "System" cmd.exe erhalten, indem Sie einen Task für cmd.exe planen (der Scheduler wird als System ausgeführt):

at 15:23 /interactive "cmd.exe" 

Ändern Sie diese Zeit für etwas in naher Zukunft. Stellen Sie außerdem sicher, dass Sie sich auf der Computerkonsole befinden (wenn Sie sich in einer regulären Terminalserversitzung befinden, wird die neue Datei cmd.exe nicht angezeigt. mstscMelden Sie sich bei der Konsole an.). Ich denke, es gibt andere Möglichkeiten, das zu tun, aber das hat in der Vergangenheit für mich funktioniert.


0

Ich hatte das gleiche Problem. Der Prozess wurde debuggt, während er abstürzte, und es gab immer noch einen vsjitdebugger.exe-Prozess in einem angehaltenen Zustand, der offenbar auf den Prozess verwies, der debuggt wurde. Das Problem wurde durch das Beenden dieses vsjitdebugger.exe-Prozesses behoben.


0

Eine hybride Verwendung von TCPView und Process Explorer hat bei mir funktioniert;) Ich habe zuerst nach der Prozess-ID gesucht, die den Port in TCPView verwendet hat. Isolierte den Prozess im Prozess-Explorer und beendete ihn mit dem Prozess-Explorer.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.