bluetooth: Fix crash on disconnection

When a Bluetooth headset is connected only to HFP profile (not connected
to A2DP) and host streams to it, a crash occurs if host disconnects.

When HFP disconnects, audio thread will fail on POLLHUP then generate
a message to set PA profile to Off before ending.
If this message is managed before PA unload bluetooth device module,
all works fine.
But, if this message is managed during module unload, this finish by
re-entrance in release code (stop_thread) and a crash.

This fix prevents to process profile change when module is unloading.
This commit is contained in:
Frédéric Danis 2012-05-15 15:55:36 +02:00 committed by Tanu Kaskinen
parent 1a6c9dc0a4
commit 21b1d92b79

View file

@ -187,7 +187,7 @@ struct userdata {
}; };
enum { enum {
BLUETOOTH_MESSAGE_SET_PROFILE, BLUETOOTH_MESSAGE_IO_THREAD_FAILED,
BLUETOOTH_MESSAGE_MAX BLUETOOTH_MESSAGE_MAX
}; };
@ -1135,12 +1135,14 @@ static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t o
struct bluetooth_msg *u = BLUETOOTH_MSG(obj); struct bluetooth_msg *u = BLUETOOTH_MSG(obj);
switch (code) { switch (code) {
case BLUETOOTH_MESSAGE_SET_PROFILE: { case BLUETOOTH_MESSAGE_IO_THREAD_FAILED: {
const char *profile = data; if (u->card->module->unload_requested)
pa_log_debug("Switch profile to %s requested", profile); break;
if (pa_card_set_profile(u->card, profile, FALSE) < 0) pa_log_debug("Switching the profile to off due to IO thread failure.");
pa_log_debug("Failed to switch profile to %s", profile);
if (pa_card_set_profile(u->card, "off", FALSE) < 0)
pa_log_debug("Failed to switch profile to off");
break; break;
} }
} }
@ -1750,7 +1752,7 @@ static void thread_func(void *userdata) {
fail: fail:
/* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */ /* If this was no regular exit from the loop we have to continue processing messages until we receive PA_MESSAGE_SHUTDOWN */
pa_log_debug("IO thread failed"); pa_log_debug("IO thread failed");
pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->msg), BLUETOOTH_MESSAGE_SET_PROFILE, "off", 0, NULL, NULL); pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(u->msg), BLUETOOTH_MESSAGE_IO_THREAD_FAILED, NULL, 0, NULL, NULL);
pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
finish: finish: