Skip to content

Commit

Permalink
sys/program_stop: add hack to workaround Bluetooth lockup
Browse files Browse the repository at this point in the history
Many Bluetooth tasks can get stuck (can't be canceled) if the Bluetooth
chip crashes. Adding checks for this at every yield point would be
very expensive in terms of code size. So for now, we just add another
hack to cancel all tasks on shutdown to avoid undefined behavior.

In some cases, this undefined behavior was causing the hub to not power
off unless the batteries were removed.

Issue: pybricks/support#1095
  • Loading branch information
dlech committed Jun 5, 2023
1 parent 0e8252b commit 7a8a849
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

## [Unreleased]

### Fixed
- Fixed hub will not power off when Bluetooth chip crashes on City and Technic hubs ([support#1095]).

[support#1095]: https://github.com/pybricks/support/issues/1095


## [3.3.0b6] - 2023-06-02

### Added
Expand Down
7 changes: 7 additions & 0 deletions lib/pbio/sys/program_stop.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <stdbool.h>
#include <stddef.h>

#include <pbdrv/bluetooth.h>
#include <pbio/button.h>
#include <pbio/main.h>

Expand All @@ -31,6 +32,12 @@ static bool stop_button_pressed;
*/
void pbsys_program_stop(bool force_stop) {
if (pbsys_status_test(PBIO_PYBRICKS_STATUS_USER_PROGRAM_RUNNING)) {
if (force_stop) {
// HACK: Bluetooth drivers have issues with pending tasks not being
// cancellable, so this should force them to be canceled and avoid
// undefined behavior due to use after free.
pbdrv_bluetooth_power_on(false);
}
pbsys_main_stop_program(force_stop);
}
}
Expand Down
1 change: 1 addition & 0 deletions pybricks/util_pb/pb_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void pb_wait_task(pbio_task_t *task, mp_int_t timeout) {
// requested. See https://github.com/pybricks/pybricks-micropython/pull/129
// We can remove this hack once we can ensure that task
// cancellation does not fail (for known cases).
// Also see hack in pbsys_program_stop().
&& !pbsys_status_test(PBIO_PYBRICKS_STATUS_SHUTDOWN_REQUEST)
#endif
) {
Expand Down

0 comments on commit 7a8a849

Please sign in to comment.