Socket.close()永远不会返回,导致操作系统出现TimeoutException

时间:2014-02-18 02:08:04

标签: android apache-httpclient-4.x

我正在使用HTTPClient库,我遇到一个奇怪的问题,即Socket.close()调用永远不会返回,导致TimeoutException。偶尔会发生这种情况,我可以在大约10%的时间内重现它。

我在Android 4.2,4.3和4.4上看到了这个问题。

以下是我为此问题创建的Android Bug Ticket:
http://code.google.com/p/android/issues/detail?id=66102

为什么Socket.close会永远挂起来?我怎么能避免这个?谢谢!

02-17 20:48:31.800: E/AndroidRuntime(12871): FATAL EXCEPTION: FinalizerWatchdogDaemon
02-17 20:48:31.800: E/AndroidRuntime(12871): Process: com.vblast.sample, PID: 12871
02-17 20:48:31.800: E/AndroidRuntime(12871): java.util.concurrent.TimeoutException: org.apache.http.impl.conn.PoolingHttpClientConnectionManager.finalize() timed out after 10 seconds
02-17 20:48:31.800: E/AndroidRuntime(12871):    at libcore.io.Posix.close(Native Method)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at libcore.io.BlockGuardOs.close(BlockGuardOs.java:75)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at libcore.io.IoBridge.closeSocket(IoBridge.java:188)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at java.net.PlainSocketImpl.close(PlainSocketImpl.java:162)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at java.net.Socket.close(Socket.java:317)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at org.apache.http.impl.BHttpConnectionBase.close(BHttpConnectionBase.java:346)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at org.apache.http.impl.conn.LoggingManagedHttpClientConnection.close(LoggingManagedHttpClientConnection.java:83)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at org.apache.http.impl.conn.CPoolEntry.closeConnection(CPoolEntry.java:70)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at org.apache.http.impl.conn.CPoolEntry.close(CPoolEntry.java:96)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at org.apache.http.pool.AbstractConnPool.shutdown(AbstractConnPool.java:127)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.shutdown(PoolingHttpClientConnectionManager.java:347)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.finalize(PoolingHttpClientConnectionManager.java:168)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:187)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:170)
02-17 20:48:31.800: E/AndroidRuntime(12871):    at java.lang.Thread.run(Thread.java:841)

2 个答案:

答案 0 :(得分:2)

原来我混淆使用Socket.setSoLinger()作为我的连接超时设置导致长时间挂起,从而导致TimeoutException。 :/

这是Socket.setSoLinger()的作用:

  

如果套接字处于连接模式,则设置SO_LINGER选项   对于具有非零逗留时间的套接字,并且套接字具有   未发送的数据,则close()将阻塞直到当前   延迟间隔,直到所有数据都被传输。

http://pubs.opengroup.org/onlinepubs/009695399/functions/close.html

答案 1 :(得分:0)

这里真正的问题是你泄漏了连接,要求它在完成时关闭。您需要检查代码以确保关闭在finally块中。您可能还必须自己调用HttpURLConnection.disconnect()。