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. Following are crash traces: D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C becomes busy. D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.MediaTransport, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.MediaTransport, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.MediaTransport, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.MediaTransport, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.MediaTransport, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.MediaTransport, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd20, member=PropertyChanged I: [pulseaudio] module-suspend-on-idle.c: Source bluez_source.10_04_14_D1_96_1C idle for too long, suspending ... D: [pulseaudio] source.c: Suspend cause of source bluez_source.10_04_14_D1_96_1C is 0x0004, suspending D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Headset, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] bluetooth-util.c: dbus: property 'State' changed to value 'disconnected' D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Headset, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Headset, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Headset, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Headset, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Headset, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] bluetooth-util.c: dbus: interface=org.bluez.Audio, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] bluetooth-util.c: dbus: property 'State' changed to value 'disconnected' D: [pulseaudio] module-bluetooth-discover.c: Unloading module for /org/bluez/7555/hci0/dev_10_04_14_D1_96_1C D: [pulseaudio] module-console-kit.c: dbus: interface=org.bluez.Audio, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged D: [pulseaudio] module-bluetooth-device.c: dbus: interface=org.bluez.Audio, path=/org/bluez/7555/hci0/dev_10_04_14_D1_96_1C, member=PropertyChanged I: [pulseaudio] module.c: Unloading "module-bluetooth-device" (index: #19). D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C becomes idle, timeout in 5 seconds. I: [bluetooth] module-bluetooth-device.c: FD error: POLLHUP D: [bluetooth] module-bluetooth-device.c: IO thread failed D: [bluetooth] sink-input.c: Have to rewind 2130 bytes on render memblockq. D: [bluetooth] sink-input.c: Have to rewind 11742 bytes on implementor. D: [bluetooth] sink.c: Requesting rewind due to started move D: [pulseaudio] module-suspend-on-idle.c: Sink bluez_sink.10_04_14_D1_96_1C becomes idle, timeout in 5 seconds. I: [pulseaudio] sink-input.c: Trying to change sample rate I: [pulseaudio] alsa-sink.c: Updating rate for device front:0, new rate is 44100 I: [pulseaudio] sink.c: Changed sampling rate successfully I: [pulseaudio] sink-input.c: Rate changed to 44100 Hz I: [pulseaudio] protocol-native.c: Requested tlength=200,00 ms, minreq=10,00 ms D: [pulseaudio] protocol-native.c: Adjust latency mode enabled, configuring sink latency to half of overall latency. D: [pulseaudio] protocol-native.c: Requested latency=90,00 ms, Received latency=90,00 ms I: [pulseaudio] resampler.c: Forcing resampler 'copy', because of fixed, identical sample rates. D: [pulseaudio] resampler.c: Channel matrix: D: [pulseaudio] resampler.c: I00 D: [pulseaudio] resampler.c: +------ D: [pulseaudio] resampler.c: O00 | 1,000 D: [pulseaudio] resampler.c: O01 | 1,000 I: [pulseaudio] remap_sse.c: Using SSE mono to stereo remapping I: [pulseaudio] resampler.c: Using resampler 'copy' I: [pulseaudio] resampler.c: Using s16le as working format. D: [pulseaudio] memblockq.c: memblockq requested: maxlength=33554432, tlength=0, base=4, prebuf=0, minreq=1 maxrewind=0 D: [pulseaudio] memblockq.c: memblockq sanitized: maxlength=33554432, tlength=33554432, base=4, prebuf=0, minreq=4 maxrewind=0 D: [pulseaudio] sink-input.c: Updated resampler for sink input 0 D: [alsa-sink] sink.c: Requesting rewind due to finished move D: [alsa-sink] alsa-sink.c: Requested volume: 0: 27% 1: 27% D: [alsa-sink] alsa-sink.c: in dB: 0: -33,76 dB 1: -33,76 dB D: [alsa-sink] alsa-sink.c: Got hardware volume: 0: 27% 1: 27% D: [alsa-sink] alsa-sink.c: in dB: 0: -33,75 dB 1: -33,75 dB D: [alsa-sink] alsa-sink.c: Calculated software volume: 0: 100% 1: 100% (accurate-enough=yes) D: [alsa-sink] alsa-sink.c: in dB: 0: -0,01 dB 1: -0,01 dB D: [alsa-sink] sink.c: Volume not changing D: [pulseaudio] sink-input.c: Successfully moved sink input 0 to alsa_output.pci-0000_00_1b.0.analog-stereo. D: [pulseaudio] sink.c: Suspend cause of sink alsa_output.pci-0000_00_1b.0.analog-stereo is 0x0000, resuming I: [alsa-sink] alsa-sink.c: Trying resume... I: [alsa-sink] alsa-util.c: Trying to disable ALSA period wakeups, using timers only D: [alsa-sink] alsa-util.c: Maximum hw buffer size is 371 ms D: [alsa-sink] alsa-util.c: Set buffer size first (to 16384 samples), period size second (to 8192 samples). I: [alsa-sink] alsa-util.c: ALSA period wakeups disabled D: [alsa-sink] alsa-sink.c: Latency set to 90,00ms D: [alsa-sink] alsa-sink.c: hwbuf_unused=49660 D: [alsa-sink] alsa-sink.c: setting avail_min=15503 I: [alsa-sink] alsa-sink.c: Time scheduling watermark is 20,00ms I: [alsa-sink] alsa-sink.c: Resumed successfully... I: [alsa-sink] alsa-sink.c: Starting playback. D: [alsa-sink] alsa-sink.c: Cutting sleep time for the initial iterations by half. D: [alsa-sink] alsa-sink.c: Cutting sleep time for the initial iterations by half. D: [alsa-sink] alsa-sink.c: Cutting sleep time for the initial iterations by half. D: [pulseaudio] module-suspend-on-idle.c: Sink alsa_output.pci-0000_00_1b.0.analog-stereo becomes busy. I: [pulseaudio] module-rescue-streams.c: Successfully moved sink input 0 "Rhythmbox" to alsa_output.pci-0000_00_1b.0.analog-stereo. D: [pulseaudio] module-rescue-streams.c: No source outputs to move away. D: [pulseaudio] core-subscribe.c: Dropped redundant event due to remove event. D: [pulseaudio] module-rescue-streams.c: No source outputs to move away. D: [bluetooth] module-bluetooth-device.c: IO thread shutting down [Thread 0x7fffe4e9d700 (LWP 6943) exited] I: [pulseaudio] sink.c: Freeing sink 1 "bluez_sink.10_04_14_D1_96_1C" I: [pulseaudio] source.c: Freeing source 2 "bluez_sink.10_04_14_D1_96_1C.monitor" I: [pulseaudio] source.c: Freeing source 3 "bluez_source.10_04_14_D1_96_1C" Breakpoint 1, pa_thread_mq_done (q=0x728950) at pulsecore/thread-mq.c:98 98 pa_assert(q); (gdb) print *q $1 = {mainloop = 0x640be8, inq = 0x712ba0, outq = 0x66d7a0, read_event = 0x6e27d0, write_event = 0x728e00} (gdb) bt #0 pa_thread_mq_done (q=0x728950) at pulsecore/thread-mq.c:98 #1 0x00007fffed93a3cc in stop_thread (u=0x7288f0) at modules/bluetooth/module-bluetooth-device.c:2560 #2 0x00007fffed93c65a in module_bluetooth_device_LTX_pa__done (m=0x727300) at modules/bluetooth/module-bluetooth-device.c:3098 #3 0x00007fffed6abb80 in pa_module_free (m=0x727300) at pulsecore/module.c:162 #4 0x00007fffed6abd66 in pa_module_unload (c=0x640d50, m=0x727300, force=true) at pulsecore/module.c:188 #5 0x00007fffed6abff1 in defer_cb (api=0x640be8, e=0x689b30, userdata=0x640d50) at pulsecore/module.c:228 #6 0x00007fffed1d7559 in dispatch_defer (m=0x640b90) at pulse/mainloop.c:702 #7 0x00007fffed1d8195 in pa_mainloop_dispatch (m=0x640b90) at pulse/mainloop.c:918 #8 0x00007fffed1d8361 in pa_mainloop_iterate (m=0x640b90, block=1, retval=0x7fffffffddb8) at pulse/mainloop.c:958 #9 0x00007fffed1d83bf in pa_mainloop_run (m=0x640b90, retval=0x7fffffffddb8) at pulse/mainloop.c:973 #10 0x0000000000422c5a in main (argc=4, argv=0x7fffffffdfe8) at daemon/main.c:1135 (gdb) c Continuing. D: [pulseaudio] module-bluetooth-device.c: Switch profile to off requested Breakpoint 1, pa_thread_mq_done (q=0x728950) at pulsecore/thread-mq.c:98 98 pa_assert(q); (gdb) print *q $2 = {mainloop = 0x640be8, inq = 0x712ba0, outq = 0x66d7a0, read_event = 0x6e27d0, write_event = 0x728e00} (gdb) bt #0 pa_thread_mq_done (q=0x728950) at pulsecore/thread-mq.c:98 #1 0x00007fffed93a3cc in stop_thread (u=0x7288f0) at modules/bluetooth/module-bluetooth-device.c:2560 #2 0x00007fffed93af09 in card_set_profile (c=0x70e7e0, new_profile=0x7141b0) at modules/bluetooth/module-bluetooth-device.c:2700 #3 0x00007fffed6a2a2b in pa_card_set_profile (c=0x70e7e0, name=0x7fffed93d8b1 "off", save=false) at pulsecore/card.c:242 #4 0x00007fffed93471d in device_process_msg (obj=0x728240, code=0, data=0x7fffed93d8b1, offset=0, chunk=0x0) at modules/bluetooth/module-bluetooth-device.c:1143 #5 0x00007fffed6923ce in pa_asyncmsgq_dispatch (object=0x728240, code=0, userdata=0x7fffed93d8b1, offset=0, memchunk=0x7fffffffd990) at pulsecore/asyncmsgq.c:322 #6 0x00007fffed6924d4 in pa_asyncmsgq_flush (a=0x66d7a0, run=true) at pulsecore/asyncmsgq.c:347 #7 0x00007fffed6f9c15 in pa_thread_mq_done (q=0x728950) at pulsecore/thread-mq.c:107 #8 0x00007fffed93a3cc in stop_thread (u=0x7288f0) at modules/bluetooth/module-bluetooth-device.c:2560 #9 0x00007fffed93c65a in module_bluetooth_device_LTX_pa__done (m=0x727300) at modules/bluetooth/module-bluetooth-device.c:3098 #10 0x00007fffed6abb80 in pa_module_free (m=0x727300) at pulsecore/module.c:162 #11 0x00007fffed6abd66 in pa_module_unload (c=0x640d50, m=0x727300, force=true) at pulsecore/module.c:188 #12 0x00007fffed6abff1 in defer_cb (api=0x640be8, e=0x689b30, userdata=0x640d50) at pulsecore/module.c:228 #13 0x00007fffed1d7559 in dispatch_defer (m=0x640b90) at pulse/mainloop.c:702 #14 0x00007fffed1d8195 in pa_mainloop_dispatch (m=0x640b90) at pulse/mainloop.c:918 #15 0x00007fffed1d8361 in pa_mainloop_iterate (m=0x640b90, block=1, retval=0x7fffffffddb8) at pulse/mainloop.c:958 #16 0x00007fffed1d83bf in pa_mainloop_run (m=0x640b90, retval=0x7fffffffddb8) at pulse/mainloop.c:973 #17 0x0000000000422c5a in main (argc=4, argv=0x7fffffffdfe8) at daemon/main.c:1135 (gdb) c Continuing. D: [pulseaudio] module-bluetooth-device.c: Releasing transport /org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd19 E: [pulseaudio] bluetooth-util.c: Failed to release transport /org/bluez/7555/hci0/dev_10_04_14_D1_96_1C/fd19: Method "Release" with signature "s" on interface "org.bluez.MediaTransport" doesn't exist bt_audio_service_open: connect() failed: Connection refused (111) W: [pulseaudio] module-bluetooth-device.c: Bluetooth audio service not available I: [pulseaudio] card.c: Changed profile of card 1 "bluez_card.10_04_14_D1_96_1C" to off Program received signal SIGSEGV, Segmentation fault. 0x00007fffed6f9c1c in pa_thread_mq_done (q=0x728950) at pulsecore/thread-mq.c:109 109 q->mainloop->io_free(q->read_event); (gdb) print *q $3 = {mainloop = 0x0, inq = 0x0, outq = 0x0, read_event = 0x0, write_event = 0x0} (gdb) bt #0 0x00007fffed6f9c1c in pa_thread_mq_done (q=0x728950) at pulsecore/thread-mq.c:109 #1 0x00007fffed93a3cc in stop_thread (u=0x7288f0) at modules/bluetooth/module-bluetooth-device.c:2560 #2 0x00007fffed93c65a in module_bluetooth_device_LTX_pa__done (m=0x727300) at modules/bluetooth/module-bluetooth-device.c:3098 #3 0x00007fffed6abb80 in pa_module_free (m=0x727300) at pulsecore/module.c:162 #4 0x00007fffed6abd66 in pa_module_unload (c=0x640d50, m=0x727300, force=true) at pulsecore/module.c:188 #5 0x00007fffed6abff1 in defer_cb (api=0x640be8, e=0x689b30, userdata=0x640d50) at pulsecore/module.c:228 #6 0x00007fffed1d7559 in dispatch_defer (m=0x640b90) at pulse/mainloop.c:702 #7 0x00007fffed1d8195 in pa_mainloop_dispatch (m=0x640b90) at pulse/mainloop.c:918 #8 0x00007fffed1d8361 in pa_mainloop_iterate (m=0x640b90, block=1, retval=0x7fffffffddb8) at pulse/mainloop.c:958 #9 0x00007fffed1d83bf in pa_mainloop_run (m=0x640b90, retval=0x7fffffffddb8) at pulse/mainloop.c:973 #10 0x0000000000422c5a in main (argc=4, argv=0x7fffffffdfe8) at daemon/main.c:1135 (gdb) --- src/modules/bluetooth/module-bluetooth-device.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index b7945ed..6716029 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -187,7 +187,7 @@ struct userdata { }; enum { - BLUETOOTH_MESSAGE_SET_PROFILE, + BLUETOOTH_MESSAGE_IO_THREAD_FAILED, 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); switch (code) { - case BLUETOOTH_MESSAGE_SET_PROFILE: { - const char *profile = data; - pa_log_debug("Switch profile to %s requested", profile); + case BLUETOOTH_MESSAGE_IO_THREAD_FAILED: { + if (u->card->module->unload_requested) + break; + + pa_log_debug("Switch profile to off requested"); - if (pa_card_set_profile(u->card, profile, FALSE) < 0) - 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; } } @@ -1750,7 +1752,7 @@ static void thread_func(void *userdata) { fail: /* 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_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); finish: -- 1.7.9.5