curl http://www.geo-mobile.com/nuke/index.php
You have to use a separate timer thread to timeout any reads.
try {
URLConnection con = urlObj.openConnection();
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
new Thread(new InterruptThread(Thread.currentThread(), con)).start();
retVal = new Source(con);
} catch (IOException e) {
System.err.println("aborted parsing due to I/O: " + e.getMessage());
throw new IndexingException("aborted parsing due to timeout - " + aUrl);
}
In this example, the Source constructor, using the Jericho parser retrieves a web page and it can get stuck on a socket read call. The timeouts don't have any effect. And it is not possible to interrupt a thread waiting on I/O using Thread.interrupt().
The solution is the hand-crafted InterruptThread class:
public class InterruptThread implements Runnable {
Thread parent;
URLConnection con;
public InterruptThread(Thread parent, URLConnection con) {
this.parent = parent;
this.con = con;
}
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println("Timer thread forcing parent to quit connection");
((HttpURLConnection)con).disconnect();
System.out.println("Timer thread closed connection held by parent, exiting");
}
}
Here, the InterruptThread forcibly closes the URLConnection held by the parent thread, forcing the Source constructor of the parent thread to throw an IOException, which is handled by its catch block, thus avoiding the hang.
12 comments:
Thanks a lot, it seems to solve my problem with stuck connections.
Bye
Thanks men!...
any other solution besides using a new thread??
It doesn't have to be a "new" thread. If you can pass the connection to an existing thread, that would work too. but I can't think of how to tackle this with only the main thread of execution.
I've created a post with an example:
http://leakfromjavaheap.blogspot.com/2013/12/are-connecttimeout-and-readtimeout.html
Thank you so much for this trick. I have tried it on Android URLConnection and works fine.
In my case the problem is that it didn't raise the IOException. What could be happening?
Here is the log proving that was called.
11-12 10:36:23.902: I/System.out(11985): Timer thread forcing parent to quit connection
11-12 10:36:23.912: I/System.out(11985): Timer thread closed connection held by parent, exiting
Thanks so much. But I see that you create but never use Parent Thread
You mean the passed in reference to the parent thread is not used? This can be used for diagnostics - the parent thread id miht be useful specially if you use this class with multiple concurrent threads.
I think it is:
public void run() {
try {
Thread.sleep(5000);
System.out.println("Timer thread forcing parent to quit connection");
((HttpURLConnection)con).disconnect();
System.out.println("Timer thread closed connection held by parent, exiting");
} catch (InterruptedException e) {
}
}
I thought that readTimeout worked OK though?
FWIW, HttpURLConnection docs state that it is not thread safe, so it is not safe to call disconnect() from another thread while who-knows-what is going on. That said, there are no other (good) solutions to this problem.? Lovely. :)
Post a Comment