Come posso uccidere un processo che è morto ma in ascolto?


48

Sto sviluppando un'app in ascolto sulla porta 3000. Apparentemente c'è un'istanza che ascolta ancora la porta perché ogni volta che la avvio non è in grado di creare un ascoltatore (C #, TcpListener, ma questo è irrilevante) perché la porta è già prese.

Ora, l'app non esiste nel Task Manager, quindi ho cercato di trovare il suo PID e ucciderlo, il che ha portato a questo interessante risultato:

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.

Non ho mai visto questo comportamento prima e ho pensato che fosse abbastanza interessante vedere se qualcuno ha una soluzione.

AGGIORNAMENTO: Ho avviato Process Explorer e fatto una ricerca per 3000 e ho trovato questo:

<Non-existent Process>(3000): 5552

Ho cliccato con il tasto destro su di esso e ho scelto "Chiudi maniglia". Non è più in Process Explorer, ma viene comunque visualizzato in netstat e impedisce ancora all'app di avviare il listener.

AGGIORNAMENTO 2: Trovato TCPView per Windows che mostra il processo come "<non-existent>". Come con CurrPorts, non succede nulla quando provo a chiudere la connessione in questo strumento.


un po 'per curare la malattia uccidendo il paziente, ma si ferma se riavvii il computer?
Xantec,

2
In effetti, è stato sufficiente disconnettersi e
riconnettersi

Controlla se qualcuno dei programmi elencati qui aiuta
Sathyajith Bhat

1
Con la versione corrente di TCPView 3.05 "Chiudi connessione" dal menu contestuale del processo <non esistente] ha chiuso correttamente la connessione nel mio caso e liberato la porta.
Ventzy Kunev,

Risposte:


13

Per evitare infinite attese sul socket, il programma dovrebbe utilizzare la funzione setsockopt con i parametri SO_REUSEADDR e 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. 

1
Ciò ha aiutato qualcuno con questo particolare problema (socket in ascolto di un processo morto)?
Rustyx,

12

Abbiamo riscontrato lo stesso problema e abbiamo utilizzato Process Explorer di Microsoft Sysinternals per cercare l'ID del processo che non esisteva più.

Si scopre che al processo è stato fatto riferimento da diversi processi DrWatson. Uccidere quei processi ha rilasciato la porta. DrWatson viene utilizzato per inviare dump di memoria a Microsoft e questo impiegava diverse ore perché il processo che si arrestava in modo anomalo conteneva diverse decine di GB di memoria al momento.


7

Penso che si dovrebbe dare CurrPorts una prova

CurrPorts è un software di monitoraggio della rete che visualizza l'elenco di tutte le porte TCP / IP e UDP attualmente aperte sul tuo computer locale. Per ogni porta nell'elenco, vengono visualizzate anche le informazioni sul processo che ha aperto la porta, incluso il nome del processo, il percorso completo del processo, le informazioni sulla versione del processo (nome del prodotto, descrizione del file e così via), il tempo in cui il processo è stato creato e l'utente che lo ha creato.

Inoltre, CurrPorts consente di chiudere connessioni TCP indesiderate, interrompere il processo che ha aperto le porte e salvare le informazioni sulle porte TCP / UDP in file HTML, file XML o in file di testo delimitati da tabulazioni.

CurrPorts inoltre segna automaticamente con porte TCP / UDP sospette di colore rosa di proprietà di applicazioni non identificate (Applicazioni senza informazioni sulla versione e icone)

testo alternativo


4
Viene visualizzato nell'elenco sotto il nome del processo "Sistema". Ho provato a fare clic destro sull'elemento per forzare la chiusura della porta ma non succede nulla.
Srekel,

7

Il probabile problema è che il processo ha avviato un altro processo (figlio) che ha ereditato l'handle del socket ed è ancora in esecuzione.

Esistono vari modi per impedirlo, ad esempio: ProcessStartInfo.UseShellExecute = true;


1
Grazie, questa è stata una buona idea. Stavo chiamando subprocess.call(..., cwd=..., shell=True)come un lanciatore di app in un server Web Python e si è scoperto che dovevo uccidere tutti quei processi figlio per liberare il socket. La cosa strana è che sto usando shell = True. Questo mi ha infastidito per anni.
Daniel F

Non penso che l'uso di una shell porti a questo comportamento. Se si desidera terminare tutti i processi figlio quando il genitore muore, penso che il modo corretto sia quello di creare un oggetto lavoro con il flag JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE , aggiungere ogni processo figlio con AssignProcessToJobObject e consentire all'handle di chiudersi naturalmente quando il processo genitore termina.
Qris,

1

Riesci a vedere il processo in Process Explorer ? Se sì, puoi ucciderlo da lì, ma solo dopo aver indagato su cosa sia effettivamente (puoi vedere tutte le dll caricate nel processo)


1

Prova a lanciare un flag '-b' sul tuo comando netstat. Ti dirà il nome dell'eseguibile che sta usando la porta. Quindi trova quel proc nel task manager e uccidilo lì. Se non funziona, inserisci quello che è l'eseguibile che tiene aperta la porta.


Al momento non riesco a riprodurlo, ma sono abbastanza sicuro che dal momento che ogni altro tentativo (e strumento) per cercare di trovare il nome del processo fallito, netstat non sarebbe stato in grado di farlo.
Srekel,

1

Ho bisogno di menzionare il termine indugiare qui.

I dettagli sono disponibili all'indirizzo http://msdn.microsoft.com/en-us/library/ms739165.aspx

In breve: esiste un'opzione che dice al sistema socket di tenere aperto un socket anche dopo che è stato chiuso se sono presenti dati non inviati.

Nell'app C # è possibile specificare eventuali opzioni correlate tramite Socket.SetSocketOption: http://msdn.microsoft.com/en-us/library/1011kecd.aspx

Poiché tutte le cose menzionate sono correlate all'invio e ai client, ma abbiamo riscontrato problemi simili sul lavoro, alcune ricerche hanno rivelato che si potrebbe specificare l'opzione di attesa per gli ascoltatori, come mostrato nell'esempio qui: http://msdn.microsoft.com /library/system.net.sockets.tcplistener.server.aspx

Alcuni colleghi hanno parlato delle porte trattenute dal sistema operativo dopo la chiusura / chiusura dell'applicazione per circa due minuti. Detto questo, sarebbe interessante sapere se la porta è ancora in attesa per un certo periodo di tempo.


Le porte sono state tenute aperte per molto più tempo (non ricordare per quanto tempo, ma forse fino a un'ora prima che mi arrendessi e riavviato).
Srekel,

Non sono sicuro che l'opzione di indugiare sia rilevante per questo caso particolare, poiché sembra che specifichi solo cosa dovrebbe succedere dopo una chiamata a CloseSocket. Dato che sto uccidendo l'applicazione, dubito che questa funzione venga chiamata (?).
Srekel,

1

Ho riscontrato anche questo problema. Alla fine ho trovato la mia ragione. È causato dal processo principale invocato da un processo figlio popen in c / c ++. Ma il processo principale si interrompe / arresta prima di invocare pclose. Quindi la porta tratterà il processo principale ancora attivo e continuerà ad ascoltarlo.


1
Ho trovato utile questa risposta su ServerFault: serverfault.com/a/273727/8856
Harriv

1

Ho avuto lo stesso problema con xdebug, ha lasciato la porta 9000 aperta.

Sono riuscito a chiudere con cmd usando "taskkill / pid xxxx".

Il pid del processo che utilizza la porta può essere recuperato con "netstat -o".

La mia configurazione è stata vincere 7 home premium.


1

Ho avuto lo stesso problema e risolto da:

  • trovare il PID con netstat -o
  • Uccidilo con process xp

Interessante notare che a volte netstat può restituire un pid ma non il nome eseguibile corrispondente!


1

Il problema può essere causato se il processo morto ha avviato uno o più processi figlio. Se

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

è stato utilizzato per avviare un processo figlio, dipende dal valore degli handle di eredità, quindi con

bInheritHandles = false 

Windows non bloccherà la porta se il processo padre viene interrotto e il processo client è ancora in esecuzione.


1

si è verificato un problema simile quando la causa principale era un processo figlio creato ereditando le porte, il processo padre si arrestava in modo anomalo, mentre il processo figlio conteneva ancora la porta. La risoluzione era quella di identificare il processo figlio ancora in esecuzione e fermarlo. Nell'esempio qui il PID di processo inesistente era 7336

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

Per interrompere questo processo:

> taskkill /f /pid 23828

E questo ha risolto il problema.


0

Suppongo che non sia installato un firewall (o provato qualsiasi tweek di rete di Windows)?

Alcuni firewall mostrano questo tipo di comportamento e possono tenere aperte le porte.

Se ne hai uno, prova a disabilitarlo, quindi avvia il tuo programma e chiudilo e vedi cosa succede.


Purtroppo non è un'opzione, dato che non ho il controllo del firewall sul mio computer.
Srekel,

@Srekel - che firewall è? Dato che stai riscontrando problemi, personalmente ritengo che sia la causa dei problemi.
William Hilsum,

0

Poiché il processo è elencato come Sistema, molto probabilmente è possibile interromperlo al prompt dei comandi "Sistema". L'account di sistema ha più privilegi di un normale amministratore.

È possibile ottenere cmd.exe "Sistema" pianificando un'attività per cmd.exe (lo scheduler viene eseguito come Sistema):

at 15:23 /interactive "cmd.exe" 

Cambia quel tempo per qualcosa nel prossimo futuro. Assicurati anche di essere sulla console della macchina (se sei in una normale sessione di Terminal Server, non vedrai il nuovo cmd.exe. Effettua l' mstscaccesso alla console). Immagino che ci siano altri modi per farlo, ma in passato ha funzionato per me.


0

Ho avuto lo stesso problema. Il processo era in fase di debug mentre si arrestava in modo anomalo e esisteva ancora un processo vsjitdebugger.exe in uno stato sospeso, che apparentemente faceva riferimento al processo in fase di debug. Uccidere il processo vsjitdebugger.exe ha risolto il problema.


0

Un uso ibrido di TCPView e Process Explorer ha funzionato per me;) Ho prima cercato l'id del processo che stava usando la porta in TCPView. Ha isolato il processo in Process Explorer e ha ucciso il processo usando Process Explorer.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.