Como eu mato um processo que está morto, mas escutando?


48

Estou desenvolvendo um aplicativo que escuta na porta 3000. Aparentemente, há uma instância dele ainda escutando a porta, porque sempre que inicio, ela não pode criar um ouvinte (C #, TcpListener, mas isso é irrelevante) porque a porta já está ocupado.

Agora, o aplicativo não existe no Gerenciador de tarefas, então tentei encontrar seu PID e matá-lo, o que levou a este resultado interessante:

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.

Eu nunca vi esse comportamento antes e achei que era interessante o suficiente para ver se alguém tem uma solução.

UPDATE: Iniciei o Process Explorer e fiz uma pesquisa por 3000 e encontrei o seguinte:

<Non-existent Process>(3000): 5552

Cliquei com o botão direito do mouse e escolhi "Fechar identificador". Ele não está mais no Process Explorer, mas ainda aparece no netstat e ainda impede o aplicativo de iniciar o ouvinte.

ATUALIZAÇÃO 2: Encontrado o TCPView para Windows que mostra o processo como "<non-existent>". Como no CurrPorts, nada acontece quando tento fechar a conexão nesta ferramenta.


um pouco de cura da doença matando o paciente, mas para se você reiniciar o computador?
Xantec 26/11

2
Na verdade, sair e voltar novamente foi o suficiente, mas eu tenho agora conseguiu reproduzi-lo assim que eu ainda gostaria de encontrar uma solução melhor ...
Srekel

Verifique se algum dos programas listados aqui ajuda
Sathyajith Bhat

1
Com a versão atual do TCPView 3.05, "Fechar conexão" no menu de contexto do processo <não existente> fechou com êxito a conexão no meu caso e liberou a porta.
Ventzy Kunev

Respostas:


13

Para evitar intermináveis ​​esperas no soquete, seu programa deve usar a função setsockopt com os parâmetros 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
Isso ajudou alguém com esse problema específico (soquete escutando por um processo morto)?
Rustyx

12

Tivemos o mesmo problema e usamos o Process Explorer da Microsoft Sysinternals para procurar a identificação do processo que não existia mais.

Acontece que o processo foi referenciado por vários processos do DrWatson. Matar esses processos liberou a porta. O DrWatson é usado para enviar despejos de memória para a Microsoft e isso levou várias horas porque o processo travado continha várias dezenas de GBs de memória no momento.


7

Eu acho que você deveria tentar CurrPorts

CurrPorts é um software de monitoramento de rede que exibe a lista de todas as portas TCP / IP e UDP abertas no momento no computador local. Para cada porta da lista, também são exibidas informações sobre o processo que abriu a porta, incluindo o nome do processo, o caminho completo do processo, as informações da versão do processo (nome do produto, descrição do arquivo etc.), a hora em que o processo foi criado e o usuário que o criou.

Além disso, o CurrPorts permite fechar conexões TCP indesejadas, interromper o processo que abriu as portas e salvar as informações das portas TCP / UDP no arquivo HTML, XML ou no arquivo de texto delimitado por tabulações.

O CurrPorts também marca automaticamente com portas TCP / UDP suspeitas de cor rosa pertencentes a aplicativos não identificados (aplicativos sem informações e ícones da versão)

texto alternativo


4
Ele aparece na lista sob o nome do processo "Sistema". Tentei clicar com o botão direito do mouse no item para forçar o fechamento da porta, mas nada acontece.
Srekel 29/11

7

O provável problema é que seu processo iniciou outro processo (filho) que herdou o identificador de soquete e ainda está em execução.

Existem várias maneiras de evitar isso, por exemplo: ProcessStartInfo.UseShellExecute = true;


1
Obrigado, foi uma boa. Eu estava ligando subprocess.call(..., cwd=..., shell=True)como iniciador de aplicativos em um servidor web python, e eu tive que matar todos esses processos filhos para liberar o soquete. O estranho é que estou usando shell = True. Isso me irritou por muito tempo.
Daniel F

Eu não acho que o uso de um shell resulte nesse comportamento. Se você deseja finalizar todos os processos filho quando o pai morre, acho que a maneira correta é criar um Objeto de Trabalho com o sinalizador JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE , adicione cada processo filho com AssignProcessToJobObject e permita que o identificador feche naturalmente quando o processo pai terminar.
QRIS

1

Você pode ver o processo no Process Explorer ? Se sim, você pode matá-lo a partir daí, mas somente depois de investigar o que realmente é (você pode ver todas as dlls carregadas no processo)


1

Tente lançar um sinalizador '-b' no seu comando netstat. Ele informará o nome do executável que está usando a porta. Então encontre esse proc no gerenciador de tarefas e mate-o lá. Se isso não funcionar, poste o executável que está mantendo a porta aberta.


Não posso reproduzi-lo no momento, mas tenho certeza de que, como todas as outras tentativas (e ferramentas) de tentar encontrar o nome do processo falharam, o netstat também não poderia fazê-lo.
Srekel

1

Precisa mencionar o termo persistir aqui.

Detalhes podem ser encontrados em http://msdn.microsoft.com/en-us/library/ms739165.aspx

Em resumo: existe uma opção que informa ao sistema de soquetes para mantê-lo aberto, mesmo depois de fechado, se houver dados não enviados.

No aplicativo C #, você pode especificar qualquer opção relacionada via Socket.SetSocketOption: http://msdn.microsoft.com/en-us/library/1011kecd.aspx

Como todo o material mencionado está relacionado ao envio e aos clientes, mas tivemos problemas semelhantes no trabalho, algumas pesquisas revelaram que era possível especificar a opção de pausa para os ouvintes, conforme mostrado no exemplo aqui: http://msdn.microsoft.com /library/system.net.sockets.tcplistener.server.aspx

Alguns colegas falaram sobre as portas mantidas pelo sistema operacional após o encerramento / fechamento do aplicativo por cerca de dois minutos. Dado isso, seria interessante saber se a porta ainda é mantida após um certo período de tempo.


As portas foram mantidas abertas por muito mais tempo do que isso (não lembre quanto tempo, mas talvez até uma hora antes de eu desistir e reiniciar).
Srekel

Não tenho certeza se a opção remanescente é relevante para este caso específico, pois parece que apenas especifica o que deve acontecer após uma chamada para o CloseSocket. Como estou matando o aplicativo, duvido que a função seja chamada (?).
Srekel

1

Eu também encontro esse problema. Finalmente eu encontrei o meu motivo. É causado pelo processo principal chamado um processo filho pelo popen no c / c ++. Mas o processo principal travar / desligar antes de chamar pclose. Em seguida, a porta tratará o processo principal ainda ativo e continuará a ouvi-lo.


1
Eu encontrei esta resposta no ServerFault útil: serverfault.com/a/273727/8856
Harriv

1

Eu tive o mesmo problema com o xdebug, ele deixou a porta 9000 aberta.

Eu consegui fechar com o cmd usando "taskkill / pid xxxx".

O pid do processo usando a porta pode ser recuperado com "netstat -o".

Minha configuração foi ganhar 7 home premium.


1

Eu tive o mesmo problema e o corrigi:

  • localizando o PID com netstat -o
  • Mate-o com o processo xp

Interessante notar que às vezes o netstat pode retornar um pid, mas não o nome do executável correspondente!


1

O problema pode ser causado se o processo morto iniciou um ou mais processos filhos. E 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
);

foi usado para iniciar um processo filho, depende do valor das alças herdadas, portanto, com

bInheritHandles = false 

O Windows não bloqueará a porta se o processo pai estiver parado e o processo do cliente ainda estiver em execução.


1

vi um problema semelhante quando a causa raiz foi um processo filho criado herdando as portas, o processo pai travou, enquanto o processo filho ainda mantinha a porta. A resolução era identificar o processo filho ainda em execução e pará-lo. No exemplo aqui, o processo PID inexistente foi 7336

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

Para parar este processo:

> taskkill /f /pid 23828

E isso resolveu o problema.


0

Suponho que você não tenha um firewall instalado (ou tentou alguma rede do Windows duas vezes)?

Alguns firewalls exibem esse tipo de comportamento e podem manter as portas abertas.

Se você tiver um, tente desativá-lo e, em seguida, inicie o seu programa, feche-o e veja o que acontece.


Infelizmente, não é realmente uma opção, pois não tenho controle do firewall no meu computador.
Srekel

@Srekel - que firewall é esse? Como você está tendo problemas, eu pessoalmente acho que está causando os problemas.
William Hilsum

0

Como seu processo está listado como Sistema, provavelmente você pode matá-lo em um prompt de comando "Sistema". A conta do sistema tem mais privilégios do que um administrador comum.

Você pode obter o "System" cmd.exe agendando uma tarefa para o cmd.exe (o agendador é executado como System):

at 15:23 /interactive "cmd.exe" 

Mude esse tempo para algo no futuro próximo. Verifique se você está no console da máquina (se você estiver em uma sessão regular do servidor de terminal, não verá o novo cmd.exe. Faça o mstsclogin no console). Acho que existem outras maneiras de fazer isso, mas isso funcionou para mim no passado.


0

Eu tenho esse mesmo problema. O processo estava sendo depurado enquanto travava, e ainda havia um processo vsjitdebugger.exe em estado suspenso, o que aparentemente se referia ao processo que estava sendo depurado. Matar esse processo vsjitdebugger.exe resolveu o problema.


0

Um uso híbrido do TCPView e do Process Explorer funcionou para mim;) Procurei pela primeira vez a identificação do processo que estava usando a porta no TCPView. Isolado o processo no Process Explorer e eliminou o processo usando o Process Explorer.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.