问题
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.
回答1:
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.
回答2:
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
public void run() {
...
while (condition) {
if (isInterrupted())
return;
...
}
...
}
to make sure thread doesn't read anything from socket's stream. After that you could call mmSocket.close()
回答3:
I faced same problem with Android 4.4.2
in Galaxy Grand 2
device
I fixed the problem with help of answer given by @markrileybot answer
I was accessing the socket.available()
method after close()
call is done by my code.
To add more to @markrileybot answer :
I had also added condition before calling socket.close()
:
public void cancel() {
try {
if(mmSocket.isConnected()) // this is condition
mmSocket.close();
Utils.pause(1000);
} catch (IOException e) {
Log.e(TAG, "/S4B/ close() of connect socket failed", e);
}
}
1 If you are sharing same socket between multiple threads
, then this condition should be added which will prevent calling close()
if socket is already closed (not connected
)
2 Before calling socket.available()
or socket.write()
, we should check socket.isConnected()
and if it returns true
then only we should process further
来源:https://stackoverflow.com/questions/18147925/fatal-signal-11-sigsegv-when-closing-bluetoothsocket-on-android-4-2-2-and-4-3