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.
I had the exact same problem. It helped to me before closing socket call
mConnectedThread.interrupt()
from outer class, and to ConnectedThread run() method add
to make sure thread doesn't read anything from socket's stream. After that you could call mmSocket.close()
I ran into this problem as well. However, for me
close()
was not the cause. The problem was accessing the socket afterclose()
. Specifically, the call toavailable()
on the socket's inputstream after the socket was closed caused the segfault.I faced same problem with Android
4.4.2
inGalaxy Grand 2
deviceI fixed the problem with help of answer given by @markrileybot answer
I was accessing the
socket.available()
method afterclose()
call is done by my code.To add more to @markrileybot answer :
I had also added condition before calling
socket.close()
:1 If you are sharing same socket between
multiple threads
, then this condition should be added which will prevent callingclose()
if socket is already closed (not connected
)2 Before calling
socket.available()
orsocket.write()
, we should checksocket.isConnected()
and if it returnstrue
then only we should process further