Как убить процесс, который мертв, но слушает?

102554
Srekel

Я разрабатываю приложение, которое прослушивает порт 3000. Очевидно, есть экземпляр, который все еще слушает порт, потому что всякий раз, когда я запускаю его, он не может создать прослушиватель (C #, TcpListener, но это не имеет значения), потому что порт уже приняты.

Теперь приложение не существует в диспетчере задач, поэтому я попытался найти его PID и убить его, что привело к интересному результату:

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. 

Я не видел такого поведения раньше и подумал, что это достаточно интересно, чтобы увидеть, есть ли у кого-нибудь решение.

ОБНОВЛЕНИЕ: я запустил Process Explorer, выполнил поиск 3000 и нашел это:

<Non-existent Process>(3000): 5552 

Я щелкнул правой кнопкой мыши по нему и выбрал «Закрыть ручку». Его больше нет в Process Explorer, но он все еще отображается в netstat и все еще не позволяет приложению запустить слушатель.

ОБНОВЛЕНИЕ 2: Найден TCPView для Windows, который показывает процесс как "<non-existent>". Как и в случае с CurrPorts, ничего не происходит, когда я пытаюсь закрыть соединение в этом инструменте.

43
немного вылечить болезнь, убив пациента, но остановится ли это, если вы перезагрузите компьютер? Xantec 13 лет назад 0
На самом деле достаточно было выйти из системы и снова войти в нее, но теперь мне удалось воспроизвести ее, поэтому я все же хотел бы найти лучшее решение ... Srekel 13 лет назад 2
Проверьте, помогает ли любая из перечисленных программ [здесь] (http://superuser.com/questions/66474/cannot-kill-process-in-vista-64) Sathya 13 лет назад 0
Сатья, спасибо, но они этого не сделали. Боюсь, больше о файлах, чем о портах. Srekel 13 лет назад 0
@Srekel хорошо .. Я отправил ответ, который может помочь вам. Sathya 13 лет назад 0
Возможно, вам стоит разобраться, как именно вы осуществляете прослушивание через порт. Возможно, это ошибка в вашей реализации или в C #. (Управление памятью возможно?) Moshe 13 лет назад 0
@ Моше: Смотри мой ответ. harrymc 13 лет назад 0
@srekel какие-нибудь обновления? Sathya 13 лет назад 0
У меня точно такая же проблема ... черт, нет ответа здесь! mmmmmmmm 11 лет назад 0
Извините, я не думаю, что когда-либо нашел решение проблемы и с тех пор покинул компанию. : / Srekel 11 лет назад 0
Добавьте опцию `/ T` (` taskkill / F / T / PID 17888`), чтобы также убить дочерние элементы, и ошибка меняется интересным образом: `ОШИБКА Процесс с PID 17888 (дочерний процесс с PID 17880) не может быть завершен , Причина: нет запущенного экземпляра задачи. В этом случае 17888 работает, а 17880 - нет. Итак, у меня есть осиротевший процесс, заблокированный мертвым родителем. Jesse Chisholm 8 лет назад 0

16 ответов на вопрос

13
harrymc

Чтобы избежать бесконечного ожидания в сокете, ваша программа должна использовать функцию setsockopt с параметрами SO_REUSEADDR и 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.  
Помогло ли это кому-нибудь с этой конкретной проблемой (прослушивание сокета через мертвый процесс)? rustyx 6 лет назад 1
11
David

We had the same problem and used Process Explorer from Microsoft Sysinternals to look up the process ID that no longer existed.

It turns out that the process was referenced by several DrWatson processes. Killing those processes released the port. DrWatson is used to send memory dumps to Microsoft and this was taking several hours because the process that crashed held several tens of GBs of memory at the time.

7
Sathya

Я думаю, вы должны попробовать CurrPorts

CurrPorts - это программное обеспечение для мониторинга сети, которое отображает список всех открытых на данный момент портов TCP / IP и UDP на вашем локальном компьютере. Для каждого порта в списке также отображается информация о процессе, открывшем порт, включая имя процесса, полный путь процесса, информацию о версии процесса (название продукта, описание файла и т. Д.), Время, в течение которого процесс был создан, и пользователь, который создал его.

Кроме того, CurrPorts позволяет закрывать нежелательные TCP-соединения, завершать процесс, который открыл порты, и сохранять информацию о портах TCP / UDP в файл HTML, файл XML или текстовый файл с разделителями табуляции.

CurrPorts также автоматически помечает розовым цветом подозрительные порты TCP / UDP, принадлежащие неопознанным приложениям (приложения без информации о версии и значков)

альтернативный текст

Он отображается в списке под именем процесса «Система». Я попытался щелкнуть правой кнопкой мыши по пункту, чтобы принудительно закрыть порт, но ничего не происходит. Srekel 13 лет назад 4
5
Nick Westgate

Вероятная проблема состоит в том, что ваш процесс запустил другой (дочерний) процесс, который унаследовал дескриптор сокета, и он все еще выполняется.

Существует несколько способов предотвратить это, например: ProcessStartInfo.UseShellExecute = true;

Спасибо, это было хорошо. Я вызывал `subprocess.call (..., cwd = ..., shell = True)` как средство запуска приложений на веб-сервере python, и оказалось, что мне пришлось убить все эти дочерние процессы, чтобы освободить разъем. Странно то, что я использую shell = True. Это меня раздражало целую вечность. Daniel F 9 лет назад 1
Я не думаю, что использование оболочки приводит к такому поведению. Если вы хотите завершить все дочерние процессы, когда родитель умирает, я думаю, что правильный способ - создать [Объект задания] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684161 (v = vs.85) .aspx) с флагом [JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684147 (v = vs.85) .aspx), добавьте каждого дочернего элемента обрабатывать с помощью [AssignProcessToJobObject] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms681949 (v = vs.85) .aspx) и разрешать естественное закрытие дескриптора при выходе из родительского процесса , qris 6 лет назад 0
1
Jakub Konecki

Можете ли вы увидеть процесс в Process Explorer ? Если да, то вы можете убить его оттуда, но только после того, как вы исследуете, что это на самом деле (вы можете увидеть все dll, загруженные в процесс)

1
Ge3ng

Попробуйте добавить флаг -b в команду netstat. Он скажет вам имя исполняемого файла, который использует порт. Затем найдите этот процесс в диспетчере задач и убейте его там. Если это не сработает, напишите, какой исполняемый файл удерживает порт открытым.

Я не могу воспроизвести его в данный момент, но я почти уверен, что, поскольку любая другая попытка (и инструмент) попытаться найти имя процесса не удалась, netstat также не смог бы это сделать. Srekel 13 лет назад 0
1
Andreas

Нужно упомянуть термин задержаться здесь.

Подробности можно найти на http://msdn.microsoft.com/en-us/library/ms739165.aspx

Вкратце: есть опция, которая сообщает системе сокетов держать сокет открытым даже после его закрытия, если присутствуют неотправленные данные.

В вашем приложении C # вы можете указать любые связанные параметры через Socket.SetSocketOption: http://msdn.microsoft.com/en-us/library/1011kecd.aspx

Поскольку все упомянутое относится к отправке и клиентам, но у нас были похожие проблемы в работе, некоторые дальнейшие поиски показали, что можно указать опцию linger для слушателей, как показано в примере здесь: http://msdn.microsoft.com /library/system.net.sockets.tcplistener.server.aspx

Некоторые коллеги говорили о том, что порты удерживаются ОС после завершения / закрытия приложения в течение примерно двух минут. Учитывая это, было бы интересно узнать, удерживается ли порт по прошествии определенного времени.

Порты были открыты гораздо дольше (не помню, как долго, но, может быть, за час до того, как я сдался и перезагрузился). Srekel 13 лет назад 0
Я не уверен, относится ли опция linger к данному конкретному случаю, так как кажется, что она определяет только то, что должно произойти после вызова CloseSocket. Поскольку я убиваю приложение, я сомневаюсь, что функция вызывается (?). Srekel 13 лет назад 0
1
lorry.lee

Я также сталкиваюсь с этой проблемой. Наконец я нашел причину. Это вызвано тем, что основной процесс вызывает дочерний процесс с помощью popen в c / c ++. Но основной процесс сбоя / выключения перед вызовом pclose. Тогда порт будет обрабатывать основной процесс еще живым и все равно слушать его.

Я нашел этот ответ на ServerFault полезным: http://serverfault.com/a/273727/8856 Harriv 11 лет назад 1
1
Christoforos

I had the same problem with xdebug, it left port 9000 open.

I managed to close with cmd using "taskkill /pid xxxx".

The pid of the process using the port can be retrieved with "netstat -o".

My configuration was win 7 home premium.

1
eka808

I had the same problem and fixed it by :

  • finding the PID with netstat -o
  • Kill it with process xp

Interesting to note that netstat can sometimes return a pid but not the corresponding executable name !