題 Windows是否會殺死不響應信號的服務?


我的服務有效 Local System 並且有時拒絕停止。

服務進程獲得終止信號,進行清理但由於該錯誤,一些線程仍在運行。

SCM向事件日誌報告事件ID為7011:

等待來自...服務的事務響應時達到超時(30000毫秒)。

之後,服務在管理控制台和WMI的“服務”窗口中顯示為已停止。

但是,如果Windows沒有終止,它如何處理服務呢?我無法重啟服務:舊服務運行的過程仍然是鎖定文件並綁定到端口。

我希望Windows能夠殺死無響應的進程,但我找不到任何關於它的文檔或設置。

30000毫秒似乎取自 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ServicesPipeTimeout (https://support.microsoft.com/en-us/help/839803/the-windows-trace-session-manager-service-does-not-start-and-event-id)。但是在30秒之後我只得到了一個事件,過程仍在那裡。

根據崩潰轉儲,主線程已經終止,並且有些線程在socket上等待 WaitForSingleObject

我們已經向供應商報告了這個錯誤,他們正試圖修復它。但這主要是殺死這個過程的問題,無論是否可以在不重啟的情況下進行清理。


2
2017-10-29 17:07


起源


你的問題掩蓋了為什麼你不能重新啟動它的根本問題。有一個鎖定的情況,服務控制器通常會等待進程+線程正常關閉但不是。因此,您遇到了死鎖情況,在這種情況下,服務會在放棄之前等待預定義的持續時間。如果要重新啟動服務,則需要手動終止進程。如果您想要解決這個問題,您需要聯繫軟件供應商。如果您想要更深入的分析,請加載procmon和procexp以更詳細地進行診斷或轉儲和調試 - thepip3r
@ thepip3r謝謝你的建議。這個bug已經被報導了。 - George Sovetov


答案:


您的服務可能已停止,但線程仍在運行, 所以它處於一個殭屍狀態。 眾所周知,線程很難在Windows下停止,如果它們被卡住了 在不間斷的系統呼叫中,它們絕對是不可阻擋的。

唯一的解決方案是更好地設計您的服務,例如線程 可以發信號停止,並且該信號在服務中設置 OnStop()方法。

線程應始終在所有系統調用上超時,並檢查它們 觸發超時時停止條件。

替代方案可能是使用OnStop()方法 thread.Abort() 停止線程。這通常是一個壞主意,因為它是未知的 線程在停止時以及在什麼狀態下可能正在做什麼 它正在修改的資源是在中止之後 (這可能另外是無效的)。


2
2017-10-29 18:07



我甚至不知道在現代Windows中有不間斷的系統調用。哪些電話是不間斷的?我現在不能做崩潰轉儲,但是,據我記得,有兩個線程,其中一個在 WaitForSingleObject調用,另一個正在等待socket上的數據。它們都是不間斷的嗎?如果沒有,阻止它們的方法是什麼? (我剛剛發現 Win32_Thread 並將試驗它。) - George Sovetov
等待信號量可能是不間斷的,等待網絡肯定是。不要中止你的線程 - 為你所有的等待添加超時。 - harrymc
不幸的是,我無權訪問源代碼。希望供應商能盡快修復它。 - George Sovetov
只有供應商才能解決這個問題。如果您的問題及其解決方案現已明確,您可能會將答案標記為已接受。 - harrymc
當我提到 Win32_Thread 我的意思是在外部終止線程,而不是從違規進程中終止線程。但似乎線程無法從外部終止。至少, Win32_Thread 沒有方法。 (我完全同意線程應該優雅地完成並嘗試以這種方式設計我自己的應用程序。) - George Sovetov