Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

socket-io on Android httpConnection memory leak

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 .

  • Does not happen on (Android 4.4.2) Samsung GS5 device
  • It doesn't happens if i connect to a non SSL server (http vs https)
  • I'm connecting to a self signed certificate server - not sure if it's related to the leak .
  • calling socket disconnect does not free the HttpConnection objects

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.

-code

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;
    }
}
like image 249
Stanga Avatar asked Apr 10 '26 00:04

Stanga


1 Answers

OK . got it .

  • The every 12.7 sec connection leak was the ping . changing the ping interval on my server helped a little. but it turns out that httpConnection was leaked on every Msg sent to the server. so basically it was not a solution.

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") ;
    ...
}
like image 79
Stanga Avatar answered Apr 12 '26 15:04

Stanga



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!