Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop a non responsive thread

I have a file transport application that moves files between FTP servers. As any one time we can have dozens of files on the move. In order to prevent flooding the FTP servers I have a system of monitor and semaphore locks.

Every so often my FTP client freezes somewhere inside System.Net.Sockets.Socket.Receive() according to the call stack. I don't get an exception so can't deal with the problem. I'd like to cancel the thread as it is blocking other threads that want to use the FTP client.

I've considered starting the method that eventually calls System.Net.Sockets.Socket.Receive() in a new thread and aborting the thread after a time period but I'm concerned that the sockets will remain open after a thread abort. Is there a more gracefull way to kill and clean up after a non responsive thread?

like image 965
Richard210363 Avatar asked Aug 03 '12 14:08

Richard210363


1 Answers

No. There's no safe, reliable way to kill a thread without its cooperation. The mechanisms that exist can be quite heavy-handed, and/or just don't necessarily work.

  • You can attempt to Interrupt() the other thread, but that generally only interrupts a thread that's waiting/sleeping or is doing something that could block. If it's in the middle of something that doesn't involve blocking, it won't even see, much less respond to, the interrupt til it tries to block again. Which, if you have a rogue thread, may very well be "never".
  • Abort() will probably kill a thread, but it is not guaranteed either -- the thread can stubbornly refuse to die. And even if it does die, it can leave your app domain in a questionable state. (Suppose the thread is aborted just as it entered a finally block. An exception will be thrown right then and there, and that finally block won't run -- so anything it'd release (locks, native resources, whatever) will remain unreleased.)
  • Apparently even unloading the app domain just aborts the threads in it, so the uncertainties of Thread.Abort apply -- plus, if it works, it'll also kill every thread in the app domain.
  • About the only thing that's relatively safe and guaranteed to work is to kill the entire process. And if you do that, there's no guarantee about the state of external stuff. You can just guarantee that any resources held will be released/closed/whatever, not that they're in any particular state (like, say, "uncorrupted").

In this case, a better solution might be to receive asynchronously (using the real async stuff (ReceiveAsync), not BeginReceive/EndReceive). That way the thread isn't blocked in native stuff, and is more easily interruptible (if for some reason you still have to do that; async's benefits include that you don't even need a separate thread just to watch input).

like image 107
cHao Avatar answered Oct 06 '22 01:10

cHao