Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fatal signal 11 SIGSEGV when closing BluetoothSocket on Android 4.2.2 and 4.3

My application worked fine under Android 2.3.3 to 4.1.2, but since Android 4.2.2 and Android 4.3, I have a

fatal signal 11 (SIGSEGV) at 0x00....

when I close the bluetooth socket.

I've searching trough a lot of forums, and the main response is that the

BluetoothSocket.close();

is called from two different thread at the same time, but it's not the case in my code.

I'm using Samsung Galaxy Note 2 under A4.1.2 (works ok) and Nexus 4 for A4.2.2 and 4.3.

Thank you in advance for your suggestions !

EDIT 1 : here are the 2 threads that manipulate the Bluetooth socket.

the first :

    /**
 * This thread runs while attempting to make an outgoing connection with a
 * device. It runs straight through; the connection either succeeds or
 * fails.
 */
private class ConnectThread extends Thread {        
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    //private final UUID MY_UUID = java.util.UUID.randomUUID();

    public ConnectThread(BluetoothDevice device) {
        if(D) Log.d(TAG, "/S4B/ start connectThread ");
        mmDevice = device;
        BluetoothSocket connection = null;


        // Get a BluetoothSocket for a connection with the given BluetoothDevice
        try {
            if(D) Log.i(TAG,"/S4B/ Create RF Socket");
            Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
            connection = (BluetoothSocket) m.invoke(device, 1);
            //connection = device.createRfcommSocketToServiceRecord(MY_UUID);
            Utils.pause(100);
        } catch (Exception e) {
            Log.e(TAG, "/S4B/ create() failed", e);
        }
        mmSocket = connection;
        if(D) Log.i(TAG,"/S4B/ Socket initialized");
    }

    public void run() {
        if(D) Log.i(TAG, "/S4B/ BEGIN mConnectThread");
        setName("ConnectThread");

        if (mmSocket != null) {
            // Always cancel discovery because it will slow down a connection
            if(mAdapter.isDiscovering()){   
                mAdapter.cancelDiscovery();
            }

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a successful connection or an exception
                if(D) Log.i(TAG,"/S4B/ Start socket connection");
                mmSocket.connect();
                if(D) Log.i(TAG,"/S4B/ End of socket connection");
            } catch (Exception e) {
                Log.e(TAG, "/S4B/ socket connect failed", e);

                // Close the socket
                try {
                    mmSocket.close();
                    if(D) Log.i(TAG,"/S4B/ close socket");

                } catch (IOException e2) {
                    Log.e(TAG,"/S4B/ unable to close() socket during connection failure",e2);
                }
                //Turn off the bluetooth - the Bluetooth STATE_OFF Broadcast will be received in welcome.class
                connectionFailed();
                return;
            }

            // Reset the ConnectThread because we're done
            synchronized (BluetoothConnectionService.this) {
                mConnectThread = null;
            }

            // Start the connected thread
            connected(mmSocket, mmDevice);
        } else {
            BluetoothConnectionService.this.start();
            connectionFailed();
        }
    }

    public void cancel() {
        try {
            if (mmSocket != null) {
                mmSocket.close();
            }
        } catch (IOException e) {
            Log.e(TAG, "/S4B/ close() of connect socket failed", e);
        }
    }
}

and the second :

    /**
 * This thread runs during a connection with a remote device. It handles all
 * incoming and outgoing transmissions.
 */
private class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final DataInputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket) {
        Log.d(TAG, "/S4B/ Create ConnectedThread");
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the BluetoothSocket input and output streams
        try {
            if(D) Log.i(TAG,"/S4B/ Get input and output stream");
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
            isConnected = true;
        } catch (IOException e) {
            Log.e(TAG, "/S4B/ Temp sockets not created", e);
            isConnected = false;
        }

        mmInStream = new DataInputStream(tmpIn);
        mmOutStream = tmpOut;
    }

    public void run() {
        setName("ConnectedThread");
        Log.i(TAG, "/S4B/ BEGIN mConnectedThread");

        while (isConnected) {
            Utils.pause(50);
            isConnected = checkConnection();
        }

    }

    /**
     * Check if the connection is still alive
     * 
     * @return true or false
     */
    private boolean checkConnection() {
        synchronized (mmInStream) {
            try {
                int len = mmInStream.available();
                if (len > 0) {// Checks the available amount
                    byte b[] = new byte[len];
                    if(D) Log.i(TAG,"/S4B/ start mmInStream readFully");
                    mmInStream.readFully(b, 0, len);
                    mHandler.obtainMessage(MESSAGE_READ, len, -1, b).sendToTarget();
                }

                return true;

            } catch (IOException ioe) {
                Log.e(TAG, "/S4B/ check connection, disconnected", ioe);
                connectionLost();
                return false; // Connection is lost.
            }
        }
    }

    /**
     * Write to the connected OutStream.
     * 
     * @param buffer
     *            The bytes to write
     */
    public void write(byte[] buffer) {
        try {
            mmOutStream.write(buffer);
        } catch (IOException e) {
            Log.e(TAG, "/S4B/ Exception during write", e);
            connectionLost();
            return;
        }
        // Share the sent message back to the UI Activity
        mHandler.obtainMessage(MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
    }

    public void cancel() {
        try {
            mmSocket.close();
            Utils.pause(1000);
        } catch (IOException e) {

            Log.e(TAG, "/S4B/ close() of connect socket failed", e);
        }
    }
}

EDIT 2 : I tried to use only one thread to be sure that there is no access in parrallel to

BluetoothSocket

but the result is exactly the same. As soon as I call

BluetoothSocket.close();

I get the fatal signal 11 and the app crashes.

like image 651
Laurent Avatar asked Dec 04 '22 09:12

Laurent


1 Answers

I ran into this problem as well. However, for me close() was not the cause. The problem was accessing the socket after close(). Specifically, the call to available() on the socket's inputstream after the socket was closed caused the segfault.

like image 179
markrileybot Avatar answered Jan 06 '23 17:01

markrileybot