Socket.close() 永远不会返回导致操作系统上的 TimeoutException



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

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

这是我为此问题创建的Android错误票证:
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)
事实证明,

我混淆了使用Socket.setSoLinger()作为我的连接超时设置,从而导致长时间挂起,从而导致超时异常。

这就是Socket.setSoLinger()的作用:

如果套接字处于连接模式,并且设置了SO_LINGER选项 对于具有非零延迟时间的插座,并且该套接字具有 未传输的数据,则 close() 应阻止最多当前 延迟间隔,直到传输所有数据。

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

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

相关内容

最新更新