I'm using socket-io on android . ('com.github.nkzawa:socket.io-client:0.3.0')
While testing my app on Nexus 10 device (Android 4.2.1) i discovered that after calling mSocket.connect() a libcore.net.http.HttpConnection Object is created every 12.7 seconds or so by libcore.net.http.HttpConnectionPool. that causes "Too many open files error" and eventually the app freezes or crash .
while investigating the leak i created an empty android project that reproduce the leak. Below i attached only the code that was added on top an empty "hello world" project.
note that on my original app - the connection to the server is successful. onError callbacks are placed but not called. On the server side only one connection is made .Emitting and receiving Msgs is successful . Only when the HttpConnection Object count reaches to 300 or so, "too many open files" error occurs and causes various problems.
the fact that it happens only on some android versions,only on SSL connections, and that connect causes the leak but disconnect does not free it, really puzzles me.
Added to build.gradle dependencies
compile 'com.github.nkzawa:socket.io-client:0.3.0'
Added to Android Manifest
<uses-permission android:name="android.permission.INTERNET" />
Main Activity....
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
.....
mSocket.connect();
}
private TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
public void checkClientTrusted(X509Certificate[] chain,String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
private Socket mSocket;
{
try
{
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, null);
IO.setDefaultSSLContext(sc);
HttpsURLConnection.setDefaultHostnameVerifier(new RelaxedHostNameVerifier());
mSocket = IO.socket("https://10.0.0.1");
mSocket.connect() ;
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
catch (URISyntaxException e) {
e.printStackTrace();
}
}
public static class RelaxedHostNameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
OK . got it .
After a little bit of digging i found this online. http://android-developers.blogspot.co.il/2011/09/androids-http-clients.html
To summarize.
"Prior to Froyo, HttpURLConnection had some frustrating bugs. In particular, calling close() on a readable InputStream could poison the connection pool. Work around this by disabling connection pooling:"
private void disableConnectionReuseIfNecessary() {
// HTTP connection reuse which was buggy pre-froyo
if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
System.setProperty("http.keepAlive", "false");
}
}
As stated i'm suffering from this leak on Jelly bean not froyo. I removed the condition.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.setProperty("http.keepAlive", "false") ;
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With