Фатальный сигнал 11 SIGSEGV при закрытии BluetoothSocket на Android 4.2.2 и 4.3
Мое приложение работало нормально под Android 2.3.3 до 4.1.2, но, начиная с Android 4.2.2 и Android 4.3, у меня есть
fatal signal 11 (SIGSEGV) at 0x00....
когда я закрываю разъем Bluetooth.
Я искал через много форумов, и основной ответ заключается в том, что
BluetoothSocket.close();
вызывается из двух разных потоков одновременно, но в моем коде это не так.
Я использую Samsung Galaxy Note 2 под A4.1.2 (работает нормально) и Nexus 4 для A4.2.2 и 4.3.
Заранее спасибо за ваши предложения!
РЕДАКТИРОВАТЬ 1: вот два потока, которые управляют разъемом Bluetooth.
первый:
/**
* 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);
}
}
}
а второй:
/**
* 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);
}
}
}
РЕДАКТИРОВАТЬ 2: Я пытался использовать только один поток, чтобы убедиться, что нет доступа параллельно
BluetoothSocket
но результат точно такой же. Как только я позвоню
BluetoothSocket.close();
Я получаю фатальный сигнал 11 и приложение вылетает.
3 ответа
Я столкнулся с этой проблемой также. Однако для меня close()
не было причиной. Проблема была в доступе к сокету после close()
, В частности, призыв к available()
на входном потоке сокета после закрытия сокета возникла ошибка.
У меня была точно такая же проблема. Это помогло мне до закрытия сокета вызова
mConnectedThread.interrupt()
из внешнего класса и в метод ConnectedThread run() добавьте
public void run() {
...
while (condition) {
if (isInterrupted())
return;
...
}
...
}
чтобы убедиться, что поток ничего не читает из потока сокета. После этого вы можете вызвать mmSocket.close()
Я столкнулся с той же проблемой с Android 4.4.2
в Galaxy Grand 2
устройство
Я исправил проблему с помощью ответа @markrileybot answer
Я имел доступ к socket.available()
метод после close()
звонок делается по моему коду.
Чтобы добавить больше к ответу @markrileybot:
Я также добавил условие перед звонком 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 Если вы используете один и тот же сокет multiple threads
затем следует добавить это условие, которое будет препятствовать вызову close()
если сокет уже закрыт (not connected
)
2 Перед звонком socket.available()
или же socket.write()
мы должны проверить socket.isConnected()
и если он вернется true
тогда только мы должны обрабатывать дальше