views:

357

answers:

5

I have a thread that downloads some images from internet using different proxies. Sometimes it hangs, and can't be killed by any means.

public HttpURLConnection uc;
public InputStream in;

Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("server", 8080));
URL url = new URL("http://images.com/image.jpg");
uc = (HttpURLConnection)url.openConnection(proxy);
uc.setConnectTimeout(30000);
uc.setAllowUserInteraction(false);
uc.setDoOutput(true);
uc.addRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
uc.connect();

in = uc.getInputStream();

When it hangs, it freezes at the uc.getInputStream() method. I made a timer which tries to kill the thread if it's run time exceeds 3 minutes. I tried .terminate() the thread. No effect. I tried uc.disconnect() from the main thread. The method also hangs and with it, the main thread. I tried in.close(). No effect. I tried uc=null, in=null hoping for an exception that will end the thread. It keeps running. It never passes the uc.getInputStream() method.

In my last test the thread lasted over 14 hours after receiving all above commands (or various combinations). I had to kill the Java process to stop the thread.

If I just ignore the thread, and set it's instance to null, the thread doesn't die and is not cleaned by garbage collector. I know that because if I let the application running for several days, the Java process takes more and more system memory. In 3 days it took 10% of my 8Gb system RAM.

It is impossible to kill a thread whatever?

+2  A: 

Try setting uc.setReadTimeout(30000);

Jim Blackler
It works. Thanks.
Adrian
+4  A: 

It is impossible to kill a thread whatever?

In many cases, yes - especially when the thread is blocked on non-interruptible IO. You might be able to to unblock it by calling uc.getInputStream().close() from another thread. Though that might not be thread safe. HttpUrlConnection also have a setReadTimeout() you should probably set in your case.

nos
A: 

No you can't. Killing a Thread from outside is an inherently unsafe operation.

What you can do is to make the Thread voluntarily closes itself. Write the downloading thread such that it will terminate itself when a timeout is exceeded.

Lie Ryan
I wanted to do that, but the thread hangs at an API function. I have no control inside the thread after it freezes (I can't say "do{}while(alive==true)" and set alive=false whenever I want, because the while line is never executed due to API method freeze).
Adrian
+2  A: 

Along with setting the read timeout (mentioned in other replies), did you try interrupting the thread?

james
Good suggestion; it will fire an `java.io.InterruptedIOException` from wherever it got stuck and `getInputStream` is documented as being able to throw that sort of thing. (Well, a superclass of it.)
Donal Fellows
A: 

uc.setReadTimeout(30000); worked like a charm. Thank you very much for your feedback.

Adrian