我正在为在 Debian 10 (Buster) 下的 Moxa MPC-2070 平板电脑(基于 Intel Atom)上运行的商业产品开发软件,并支持 BlueZ (5.50) 蓝牙。该应用程序是使用 Qt Creator 开发的。我一直在努力寻找一种强大且可靠的方法来扫描低功耗蓝牙设备。
由于与 Qt 中的 QBluetoothDiscoveryAgent::start() 方法相关的极端性能问题(我不会在这里讨论),我正在使用 bluetoothctl 命令执行 BLE 设备扫描。bluetoothctl 的包装器为其提供输入命令并解析 bluetoothctl 的输出。偶尔(每 1 - 150 次)我启动 bluetoothctl 以执行 BLE 扫描,蓝牙守护进程(bluetoothd)因 SIGSEGV 而崩溃。
这是蓝牙崩溃后系统日志的尾部:
[315398.536280] show_signal_msg: 8 callbacks suppressed
[315398.536293] bluetoothd[523]: segfault at a8ec8148fd ip 00007f681ba3e143 sp 00007ffc8110a858 error 4 in libdbus-1.so.3.19.11[7f681ba2f000+2e000]
[315398.536343] Code: 85 ed 74 13 0a 18 88 18 48 83 c4 08 5b 5d c3 0f 1f 84 00 00 00 00 00 f7 d3 22 18 88 18 48 83 c4 08 5b 5d c3 0f 1f 00 48 8b 07 <0f> b6 40 02 85 f0 0f
95 c0 0f b6 c0 c3 55 48 89 fd 53 89 f3 48 83
我已经使用 -d 标志重新启动了蓝牙,以通过以下方式启用调试输出:
$ sudo bluetoothd -d &
并再次循环运行 bluetoothctl 扫描,直到 bluetoothd 再次崩溃。可以在此处找到显示蓝牙崩溃的完整 syslog:Complete syslog with bluetoothd SIGSEGV
在上面的 syslog 中,可以在 1 月 14 日 09:58:55 找到最初的 bluetoothd(不带 -d)崩溃。
使用 -d 标志重启蓝牙的时间是 1 月 14 日 10:03:16。
bluetoothctl 的循环使用从 1 月 14 日 10:06:03 开始。
bluetoothd 在 1 月 14 日 10:05:13 再次 SIGSEGVs。
有时 bluetoothd 崩溃仅发生在 1 或 2 个 bluetoothctl 命令之后,而其他时候它需要多次迭代才能发生崩溃。
这个 shell 脚本将重现蓝牙崩溃。它循环执行与我的 C bluetoothctl 包装程序基本相同的功能,但没有 bluetoothctl 输出处理。请注意,此脚本必须以 root 身份或由属于“蓝牙”组成员的用户 ID 运行。
#! /bin/bash
COUNT=0
RESULT=0
while [ "${RESULT}" != "9" ]
do
COUNT=`expr ${COUNT} + 1`
echo "Loop #${COUNT}"
# uveTagScanner -s FEA0 ${@} # The compiled bluetoothctl wrapper program with output processing
# RESULT="$?"
( echo "menu scan" # Enter the bluetoothctl scan sub-menu
echo "clear" # Clear all filter parameters
echo "transport le" # Filter scanning for low-energy devices only
echo "duplicate-data off" # Disable reporting of duplicate-data
echo "back" # Exit the bluetoothctl scan sub-menu & return to main menu
echo "scan on" # Start scanning for LE devices
sleep 10 # Let scanning proceed for 10 seconds
echo "scan off" # Stop scanning for LE devices
echo "quit" # Quit the bluetoothctl command
) | bluetoothctl
done
在我的 fork()/exec()s bluetoothctl 并执行输出处理的 C 包装程序 (uveTagScanner) 中,我能够检测 bluetoothd 是否崩溃然后重新启动它。但这只是一个创可贴的解决方案,因为它仍然给我留下了扫描 BLE 设备无法提供所需信息的情况。
我对如何可靠地执行 BLE 设备扫描没有任何想法!我可以尝试使用 BlueZ 库和 Dbus 接口 API 而不是 bluetoothctl,但我担心会发生同样的 bluetoothd 崩溃。