Skip to content

Possible race condition between async_context_task() and async_context_freertos_deinit() #2487

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ptahpeteh opened this issue May 23, 2025 · 0 comments

Comments

@ptahpeteh
Copy link

Tested with pico_cyw43_arch_lwip_sys_freertos and commit ee68c78.

If the thread executing async_context_freertos_deinit() has higher priority than async_context_task() then the async_context_task() does not end immediately and async_context_freertos_deinit() clears the async_context_freertos_t struct before async_context_task() exit. This results in async_context_task() using already freed freertos objects.

The course of events:

  1. When async_context_freertos_deinit() is called, it adds a synch work that sets task_should_exit = true requesting ending of the async_context_task(). Then async_context_freertos_deinit() pends on semaphore which will signal completing of the work.
  2. Context is switched to async_context_task() which will execute queued work and set task_should_exit = true. Then the semaphore is signaled as the work is completed.
  3. Since higher priority task, that is async_context_freertos_deinit(), is now unblocked, the scheduler wakes it up.
  4. async_context_freertos_deinit() then destroys all the allocated freertos object and clears the async_context_freertos_t struct (memset() at the end of the function). This effectively sets task_should_exit to false again.
  5. At later time when scheduler wakes up the async_context_task(), it finds task_should_exit false and continues to run trying to take semaphore (by calling async_context_freertos_acquire_lock_blocking()) which was already freed by the async_context_freertos_deinit() and is NULL now. This will cause the following assert() error: assertion "pxMutex" failed: file "FreeRTOS-Kernel/queue.c", line 826.

Steps to reproduce:

  1. Call the cyw43_arch_deinit() from a task that has priority equal or higher to tskIDLE_PRIORITY + 4.

Possible solutions:

  1. Setting default value of CYW43_TASK_PRIORITY to (configMAX_PRIORITIES - 1) instead of (tskIDLE_PRIORITY + 4).
  2. Implementing synchronization between async_context_freertos_deinit() and async_context_task(). For example, async_context_task() could signal an event after going out of do-while loop.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants