mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
A Bluetooth scan ran inside one task handler call, and both drivers waited out the ten-second discovery window in it: bluez in a retro_sleep(10000) between StartDiscovery and StopDiscovery, bluetoothctl in a pclose() of "bluetoothctl --timeout 10 scan on". That is the task queue's one worker thread, so for the whole window every other task - downloads, thumbnails, cloud sync - sat queued behind the scan. The driver interface's scan() becomes scan_begin() and scan_end(), BLUETOOTH_SCAN_WINDOW_US apart. The scan task calls begin, sets its own 'when' to the end of the window and returns unfinished; the task queue keeps scheduled tasks behind ready ones, so everything else runs in the meantime, and the task comes back at the end of the window to call end and finish. A cancel ends the window early. - bluez: begin powers the adapter and starts discovery on a connection it keeps open - BlueZ ends a client's discovery when its connection goes - and end stops discovery, reads the devices and disconnects. A begin that failed part way leaves end only disconnecting. The driver's free() now releases a connection a scan still holds, and the device list, which it leaked. - bluetoothctl: begin starts "scan on" with popen() and returns; end pcloses it, which by the end of the window has already exited, then lists the devices as before. free() closes a scan still running. samples/tasks/bluetooth_scan runs the scan task on the real threaded task queue against stand-in driver calls, with the window shortened to 300 ms. It pins that begin and end run once each a window apart, that another task pushed during the window runs within 100 ms, and that the scan's callback fires. Clean under ASan, UBSan and TSan; added to the samples/tasks job.