ConnectSDK / Connect-SDK-Android

Android source project for Connect SDK
Apache License 2.0
304 stars 129 forks source link

Application got Freezed on Network disconnection in Android N (7.0) device #357

Open krishnamn opened 8 years ago

krishnamn commented 8 years ago

Hi Application got freezed (ANR state) when the network got disconnected after opening the app in Nexus 9 (Android 7.0 ) . It was observed in the trace logs that a dead lock occured on com.connectsdk.discovery.provider.ssdp.SSDPClient.close . Below is the partial trace lock. Please check

`"main" prio=5 tid=1 Blocked | group="main" sCount=1 dsCount=0 obj=0x73799530 self=0xe5b04400 | sysTid=2217 nice=-4 cgrp=default sched=0/0 handle=0xe878e534 | state=S schedstat=( 3867775484 1969408624 9506 ) utm=305 stm=80 core=0 HZ=100 | stack=0xff378000-0xff37a000 stackSize=8MB | held mutexes= at java.net.DatagramSocket.disconnect(DatagramSocket.java:506)

Thread-18" prio=5 tid=68 Native | group="main" sCount=1 dsCount=0 obj=0x12d5e0d0 self=0xcacefa00 | sysTid=2339 nice=0 cgrp=default sched=0/0 handle=0xbdcff920 | state=S schedstat=( 29062667 12680420 32 ) utm=1 stm=0 core=1 HZ=100 | stack=0xbdbfd000-0xbdbff000 stackSize=1038KB | held mutexes= kernel: switch_to+0x74/0x8c kernel: skb_recv_datagram+0x328/0x360 kernel: udpv6_recvmsg+0xb8/0x700 kernel: inet_recvmsg+0x38/0x50 kernel: sock_recvmsg+0xd0/0xf4 kernel: SyS_recvfrom+0xdc/0x26c kernel: compat_sys_recvfrom+0x10/0x18 kernel: ret_fast_syscall+0x0/0x24 native: #00 pc 00049854 /system/lib/libc.so (recvfrom+16) native: #01 pc 0004fbb5 /system/lib/libc.so (recvfrom_chk+20) native: #02 pc 0000e30f /system/lib/libopenjdk.so (NET_RecvFrom+70) native: #03 pc 0001a4ab /system/lib/libopenjdk.so (PlainDatagramSocketImpl_receive0+294) native: #04 pc 000b56d9 /system/framework/arm/boot.oat (Java_java_net_PlainDatagramSocketImpl_receive0Ljava_net_DatagramPacket_2+108) at java.net.PlainDatagramSocketImpl.receive0(Native method)

krishnamn commented 8 years ago

Hi i Solved my issue by adding couple of conditions in connect sdk code.....Thanks

jjfster commented 8 years ago

I'm having the same problem. Can you please share what the solution was?

ghost commented 7 years ago

@krishnamn could you share your solution?

blunoob commented 7 years ago

@krishnamn Could you please share your solution?

marian-eremia commented 7 years ago

Did some more in-depth investigation on this and it seems Android Nougat (7) uses openJDK as runtime (effectively ditching the "standard" runtime implementation with the OpenJDK one). If you check the source for DatagramSocket.java in android-24 sources packet it differs from android-22 for example. So then the disconnect method are different:

The before:

    /**
     * Disconnects this UDP datagram socket from the remote host. This method
     * called on an unconnected socket does nothing.
     */
    public void disconnect() {
        if (isClosed() || !isConnected()) {
            return;
        }
        impl.disconnect();
        address = null;
        port = -1;
        isConnected = false;
    }

The after:

    /**
     * Disconnects the socket. If the socket is closed or not connected,
     * then this method has no effect.
     *
     * @see #connect
     */
    public void disconnect() {
        synchronized (this) {
            if (isClosed())
                return;
            if (connectState == ST_CONNECTED) {
                impl.disconnect ();
            }
            connectedAddress = null;
            connectedPort = -1;
            connectState = ST_NOT_CONNECTED;
        }
    }

Nothing wrong with this, until you look closer into the receive method:

    public synchronized void receive(DatagramPacket p) throws IOException {
        synchronized (p) {
            if (!isBound())
                bind(new InetSocketAddress(0));

            // ----- BEGIN android -----
            if (pendingConnectException != null) {
                throw new SocketException("Pending connect failure", pendingConnectException);
            }
            // ----- END android -----

            if (connectState == ST_NOT_CONNECTED) {
...

Well now we can see the issue: the disconnect method in android-24 sources actually tries to obtain a lock for the current DatagramSocket object (this) which unfortunately is locked in the receive method (if the socket is connected).

What this is, is a deadlock.

What @krishnamn probably did was to check if the socket is connected, and if so, close the socket, not disconnect it, in SSDPClient.java (connect-sdk):

So this:

    /** Close the socket */
    public void close() {
        if (multicastSocket != null) {
            try {
                multicastSocket.leaveGroup(multicastGroup, networkInterface);
            } catch (IOException e) {
                e.printStackTrace();
            }
            multicastSocket.close();
        }

        if (datagramSocket != null) {
            datagramSocket.disconnect();
            datagramSocket.close();
        }
    }

Becomes this:

    /** Close the socket */
    public void close() {
        if (multicastSocket != null) {
            try {
                multicastSocket.leaveGroup(multicastGroup, networkInterface);
            } catch (IOException e) {
                e.printStackTrace();
            }
            multicastSocket.close();
        }

        if (datagramSocket != null) {
            if (!datagramSocket.isClosed(){
                datagramSocket.close();
            }
            datagramSocket.disconnect();
            datagramSocket.close();
        }
    }

Also, FYI there are some issues with hashCode() for Enums in the OpenJDK implementation, if anyone encounters strange behavior in their apps.

krishnamn commented 7 years ago

Sorry for the late reply...In my case it got solved by handling the below cases in Connect SDk -- > SSDPClient class --> Close method

    if(this.datagramSocket != null) {
        if(this.datagramSocket.isConnected()) {
            this.datagramSocket.disconnect();
        }

        if(!this.datagramSocket.isClosed()) {
            this.datagramSocket.close();
        }
nrkdrk commented 6 years ago

Hello, I tried the solutions mentioned above, but I still could not solve the problem. Can you help me?

VishV-Android commented 11 months ago

I am getting this same issue. Is there any other solution for app freeze?

sougoukk commented 5 months ago

help I have same issue