I have made a thread which is able to read bluetooth messages sent from phone.
My problem came when I realised I have no way of killing that thread safely. Method so far was user input which called exit()
from within that thread, all weird stuff started happening when I moved that out of that thread and into the main (stack smashing detected and segmentation fault). Obviously this approach also wouldn't really scale well if I had another thread for wifi calls or just didn't want to exit everything altogether.
This is my code so far.
Struct for bluetooth related stuff to pass to the thread:
typedef struct {
struct sockaddr_rc loc_addr;
struct sockaddr_rc rem_addr;
socklen_t opt;
char blu_buffer[1024];
int blu_sock;
} Bluetooth_stuff;
Thread listening for new connections:
void * BluetoothListiner(void * argv){
Bluetooth_stuff * bt_set = (Bluetooth_stuff * ) argv;
int bytes_read;
int local_client;
int option = 0;
listen(bt_set->blu_sock, 1);
memset(bt_set->blu_buffer, 0, sizeof(bt_set->blu_buffer));
while(true){
local_client = accept(bt_set->blu_sock, (struct sockaddr *)&((*bt_set).rem_addr), &((*bt_set).opt));
// read data from the client
bytes_read = read(local_client, bt_set->blu_buffer, sizeof(bt_set->blu_buffer));
if( bytes_read > 0 ) {
// process data
}
}
else{
// accept again?
}
// clear the buffer
memset(bt_set->blu_buffer, 0, sizeof(bt_set->blu_buffer));
// close connection
close(local_client);
usleep(10);
}
}
Socket configuration:
void BluetoothSocketConfig(Bluetooth_stuff * bt_set){
// allocate socket
bt_set->blu_sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
bt_set->opt= sizeof(bt_set->rem_addr);
(*bt_set).loc_addr.rc_family = AF_BLUETOOTH;
(*bt_set).loc_addr.rc_bdaddr = *BDADDR_ANY;
(*bt_set).loc_addr.rc_channel = (uint8_t) 1;
// bind socket to port 1 of the first available
bind(bt_set->blu_sock, (struct sockaddr *)&(bt_set->loc_addr), sizeof(bt_set->loc_addr));
}
Testing main:
int main(int argc, char *argv[]){
Bluetooth_stuff bt_set;
BluetoothSocketConfig(&bt_set);
pthread_create(&blu_listiner, NULL, BluetoothListiner, bt_set);
while(1); // I modify that for testing to exit, having a global flag also gave me segmentation errors somehow
}
Calling exit(1)
doesn't clean up other threads and pthread_kill
or pthread_cancel
from another thread would often cause processes still running in the background preventing me from running the application again without manually killing processes with ps -A
and kill -9 PROCESS
.
Based on this article I figured that the best way to do that was to introduce an if
statement within the thread and have it pthread_exit
itself into the oblivion. Such as:
if(external_exit){
ret2 = 200;
pthread_exit(&ret2);
}
Now since read()
is a blocking call, I could never arrive at if
statement without something externally happening. This answer suggests using a timeout to achieve that and I followed the syntax from this answer to manage to break out from read()
after a certain period. So I had this added before the main while loop of the thread ( i think this should only be defined once rather than at every loop, though not sure as couldn't find specific example).
Now my problem was that it would block on read()
on the first loop, but then would skip it as if nothing and just loop indefinitely. I have tried to "reenable read()
", by reinvoking accept()
listen()
and bind()
with no success. It seems using select()
is the preferred option for first checking if there is anything to read, but as stated in the manual
"Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded"
So even if using it (which I'm not sure would work on bluetooth sockets as it would on tcp ones) there is always a chance it would still get stuck on read()
with no way of killing it safely.
1) How can I safely kill that thread (or any blocking thread)?
2) Is select()
really needed for blocking approach as I do not have multiple connections?
3) What is the procedure to reenable proper use of read()
in blocking mode after the initial timeout?
4) Besides different initialisation are all sockets basically equivalent unix/can/tcp/bluetooth?
5) Any other ways to get what I want or serious flaws in logic from my part?
Thank you for any help ahead, if anyone has a link to a bluetooth server thread implementation I'd be thrilled to see it (or any other socket unix/can/tcp).