pw_thread_freertos: Don't resume before scheduler is running
Calling vTaskResume() before vTaskStartScheduler() can cause
port_YIELD() to be called, resulting in a crash either now or later.
It's safe to call xTaskResumeAll() instead, so apply the fix by only
using vTaskResume() is both that method and xTaskGetSchedulerState()
are available.
No-Docs-Update-Reason: bugfix
Change-Id: I07214c2a294a29ca579aac589e80ad9a90933104
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/56548
Pigweed-Auto-Submit: Scott James Remnant <keybuk@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Reviewed-by: Keir Mierle <keir@google.com>
diff --git a/pw_thread_freertos/thread.cc b/pw_thread_freertos/thread.cc
index 7854e19..d516b65 100644
--- a/pw_thread_freertos/thread.cc
+++ b/pw_thread_freertos/thread.cc
@@ -184,18 +184,25 @@
void Thread::detach() {
PW_CHECK(joinable());
-#if INCLUDE_vTaskSuspend == 1
+#if (INCLUDE_vTaskSuspend == 1) && (INCLUDE_xTaskGetSchedulerState == 1)
// No need to suspend extra tasks.
- vTaskSuspend(native_type_->task_handle());
+ if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
+ vTaskSuspend(native_type_->task_handle());
+ }
#else
+ // Safe to suspend all tasks while scheduler is not running.
vTaskSuspendAll();
#endif // INCLUDE_vTaskSuspend == 1
native_type_->set_detached();
const bool thread_done = native_type_->thread_done();
-#if INCLUDE_vTaskSuspend == 1
- // No need to suspend extra tasks.
- vTaskResume(native_type_->task_handle());
+#if (INCLUDE_vTaskSuspend == 1) && (INCLUDE_xTaskGetSchedulerState == 1)
+ // No need to suspend extra tasks, but only safe to call once scheduler is
+ // running.
+ if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) {
+ vTaskResume(native_type_->task_handle());
+ }
#else
+ // Safe to resume all tasks while scheduler is not running.
vTaskResumeAll();
#endif // INCLUDE_vTaskSuspend == 1