Як я вбиваю процес, який є мертвим, але слухає?


48

Я розробляю додаток, який слухає порт 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.

Я ще не бачив такої поведінки і вважав, що це досить цікаво, щоб побачити, чи є у когось рішення.

ОНОВЛЕННЯ: Я запустив Провідник процесів і здійснив пошук 3000 і виявив це:

<Non-existent Process>(3000): 5552

Я правою кнопкою миші натиснув на нього і вибрав "Закрити ручку". Він більше не в Process Explorer, але все ще відображається в netstat і все ще не дозволяє додатку запускати слухача.

ОНОВЛЕННЯ 2: Знайдено TCPView для Windows, які показують процес як "<non-existent>". Як і з CurrPorts, нічого не відбувається, коли я намагаюся закрити з'єднання в цьому інструменті.


трохи вилікувати хворобу, вбивши пацієнта, але чи припиняється вона, якщо перезапустити комп’ютер?
Ксантек

2
Насправді виходу та повернення знову було достатньо, але мені зараз вдалося відтворити його, тому я все одно хотів би знайти краще рішення ...
Срекель

Перевірте, чи допомогла будь-яка з перерахованих тут програм
Sathyajith Bhat

1
З поточною версією TCPView 3.05 "Закрити з'єднання" з контекстного меню <non-exsitent> процес успішно закрив з'єднання в моєму випадку і звільнив порт.
Венці Кунев

1
Дивіться також serverfault.com/questions/181015/…
rogerdpack

Відповіді:


13

Щоб уникнути нескінченного очікування на сокет, ваша програма повинна використовувати функцію setockopt з параметрами 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. 

1
Чи допоміг це комусь із цієї проблеми (прослуховування сокета мертвим процесом)?
rustyx

12

У нас була така ж проблема і ми використовували Process Explorer від Microsoft Sysinternals, щоб шукати ідентифікатор процесу, який більше не існував.

Виявляється, на цей процес посилалося кілька процесів DrWatson. Вбивство цих процесів звільнило порт. DrWatson використовується для надсилання скидів пам’яті в Microsoft, і це займало кілька годин, оскільки процес, який зазнав аварії, у той час містив кілька десятків ГБ пам’яті.


7

Я думаю, вам варто спробувати CurrPorts

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

Крім того, CurrPorts дозволяє закрити небажані TCP-з'єднання, знищити процес, який відкрив порти, і зберегти інформацію про порти TCP / UDP в HTML-файл, XML-файл або в текстовий файл з обмеженими вкладками.

CurrPorts також автоматично позначає підозрілі порти TCP / UDP рожевого кольору, що належать невстановленим програмам (програми без інформації про версію та піктограми)

alt текст


4
Він відображається у списку під назвою процесу "Система". Я спробував правою кнопкою миші елемент, щоб змусити закрити порт, але нічого не відбувається.
Срекель

7

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

Існують різні способи запобігти цьому, наприклад: ProcessStartInfo.UseShellExecute = true;


1
Спасибі, це було добре. Я дзвонив subprocess.call(..., cwd=..., shell=True)як запуск програми на веб-сервері python, і виявилося, що мені довелося вбити всі ці дочірні процеси, щоб звільнити сокет. Дивно, що я використовую shell = True. Це мене дратувало століттями.
Даніель Ф

Я не думаю, що використання оболонки призводить до такої поведінки. Якщо ви хочете припинити всі дочірні процеси, коли батько помирає, я вважаю, що правильним способом є створення об’єкта завдання зі знаком JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE , додайте кожен дочірній процес за допомогою AssignProcessToJobObject і дозвольте ручці природним чином закриватися, коли вихідний процес закінчується.
qris

1

Чи можете ви бачити процес у Process Explorer ? Якщо так, то ви можете вбити його звідти, але лише після того, як ви дослідите, що це насправді (ви можете побачити всі dll, завантажені в процес)


1

Спробуйте кинути прапор '-b' на команду netstat. Він розповість вам ім'я виконавчого файлу, який використовує порт. Потім знайдіть цю програму в диспетчері завдань і вбити її там. Якщо це не працює, розміщуйте порт відкритим, що виконується.


Я не можу його відтворити на даний момент, але я впевнений, що оскільки кожна інша спроба (і інструмент) спроби знайти ім'я процесу не вдалася, і netstat не міг би це зробити.
Срекель

1

Тут потрібно згадати термін затримуватися .

Докладні відомості можна знайти на веб- сторінці http://msdn.microsoft.com/en-us/library/ms739165.aspx

Коротше кажучи: є опція, яка повідомляє системі сокет тримати розетку відкритою навіть після її закриття, якщо немає недоступних даних.

У вашому додатку C # ви можете вказати будь-які пов'язані параметри за допомогою Socket.SetSocketOption: http://msdn.microsoft.com/en-us/library/1011kecd.aspx

Оскільки всі згадані речі пов'язані з відправленням та клієнтами, але у нас виникли подібні проблеми на роботі, деякий подальший пошук показав, що можна вказати варіант затримки для слухачів, як показано в прикладі тут: http://msdn.microsoft.com /library/system.net.sockets.tcplistener.server.aspx

Деякі колеги говорили про порти, які ОС тримає після закінчення / закриття програми протягом двох хвилин. Враховуючи це, було б цікаво почути, чи зберігається порт через певний час.


Порти трималися відкритими набагато довше, ніж це (не пам'ятаю, як довго, але, можливо, до години, перш ніж я здався і перезавантажився).
Срекель

Я не впевнений, чи відповідає параметр затримки для даного конкретного випадку, оскільки, здається, він визначає лише те, що повинно відбутися після дзвінка до CloseSocket. Оскільки я вбиваю додаток, я сумніваюся, що ця функція викликається (?).
Срекель

1

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


1
Я вважаю цю відповідь на сервері ServerFault корисною: serverfault.com/a/273727/8856
Харрів

1

У мене була така ж проблема з xdebug, він залишив порт 9000 відкритим.

Мені вдалося закрити cmd за допомогою "taskkill / pid xxxx".

Pid процесу за допомогою порту можна отримати за допомогою "netstat -o".

Моя конфігурація була win 7 home premium.


1

У мене була така ж проблема і виправлено її:

  • знаходження PID с netstat -o
  • Вбити його за допомогою процесу xp

Цікаво зазначити, що netstat іноді може повернути pid, але не відповідне ім'я виконавця!


1

Проблема може бути викликана, якщо мертвий процес розпочав один або кілька дочірніх процесів. Якщо

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

використовувався для запуску дочірнього процесу, це залежить від значення успадкованих ручок, так з

bInheritHandles = false 

Windows не заблокує порт, якщо батьківський процес зупинений і клієнтський процес все ще працює.


1

побачив подібну проблему, коли першопричиною був якийсь дочірній процес, створений у спадок портів, батьківський процес вийшов з ладу, тоді як дочірній процес все ще тримає порт. Постанова полягала в тому, щоб ідентифікувати дочірній процес, який все ще працює, і зупинити його. У прикладі тут неіснуючий PID процесу був 7336

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

Щоб зупинити цей процес:

> taskkill /f /pid 23828

І це вирішило питання.


0

Я не думаю, що у вас встановлений брандмауер (або випробували будь-які налаштування мережі Windows)?

Деякі міжмережеві стіни проявляють подібну поведінку і можуть тримати порти відкритими.

Якщо у вас є, спробуйте відключити його, а потім запустіть програму і закрийте її і побачите, що відбувається.


На жаль, це не варіант, на жаль, оскільки я не маю контролю над брандмауером на своєму комп’ютері.
Срекель

@Srekel - що це за брандмауер? Оскільки у вас виникають проблеми, я особисто вважаю, що саме це викликає проблеми.
Вільям Гілсум

0

Оскільки ваш процес вказаний як Система, швидше за все, ви можете його вбити в командному рядку "Система". У системному обліковому записі більше привілеїв, ніж у звичайного адміністратора.

Ви можете отримати "System" cmd.exe, запланувавши завдання для cmd.exe (планувальник працює як System):

at 15:23 /interactive "cmd.exe" 

Найближчим часом змініть цей час на щось. Переконайтеся, що ви перебуваєте на машинній консолі (якщо ви перебуваєте на звичайному сеансі сервера терміналів, ви не побачите нового cmd.exe. Зробіть mstscвхід у консоль). Я думаю, є й інші способи, але це працювало для мене раніше.


0

У мене була ця сама проблема. Цей процес налагоджувався під час виходу з ладу, і все ще існував процес vsjitdebugger.exe у призупиненому стані, який затримувався навколо, який, мабуть, посилався на процес налагодження. Вбивство цього процесу vsjitdebugger.exe вирішило проблему.


0

Для мене працювало гібридне використання TCPView та Process Explorer;) Я вперше заглянув до ідентифікатора процесу, який використовував порт у TCPView. Ізолював процес у Process Explorer і вбив процес за допомогою Explorer Explorer.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.