mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-26 07:17:57 +03:00
fix(pthread): wait for child exit after unrelated notifications
This commit is contained in:
@@ -464,8 +464,14 @@ int pthread_join(pthread_t thread, void **retval)
|
||||
|
||||
if (ret == 0) {
|
||||
if (wait) {
|
||||
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
|
||||
_lock_acquire(&s_threads_lock);
|
||||
for (;;) {
|
||||
xTaskNotifyWait(0, 0, NULL, portMAX_DELAY);
|
||||
_lock_acquire(&s_threads_lock);
|
||||
if (pthread->state == PTHREAD_TASK_STATE_EXIT) {
|
||||
break;
|
||||
}
|
||||
_lock_release(&s_threads_lock);
|
||||
}
|
||||
child_task_retval = pthread->retval;
|
||||
pthread_delete(pthread);
|
||||
_lock_release(&s_threads_lock);
|
||||
@@ -536,12 +542,11 @@ void pthread_exit(void *value_ptr)
|
||||
} else {
|
||||
// Set return value
|
||||
pthread->retval = value_ptr;
|
||||
// Remove from list, it indicates that task has exited
|
||||
// Publish completion under the same lock checked by pthread_join.
|
||||
pthread->state = PTHREAD_TASK_STATE_EXIT;
|
||||
if (pthread->join_task) {
|
||||
// notify join
|
||||
xTaskNotify(pthread->join_task, 0, eNoAction);
|
||||
} else {
|
||||
pthread->state = PTHREAD_TASK_STATE_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,27 @@ TEST_CASE("pthread create join", "[pthread]")
|
||||
}
|
||||
}
|
||||
|
||||
static void *join_notification_worker(void *arg)
|
||||
{
|
||||
// Keep the child alive until the parent has entered pthread_join.
|
||||
vTaskDelay(2);
|
||||
return arg;
|
||||
}
|
||||
|
||||
TEST_CASE("pthread join ignores unrelated task notifications", "[pthread]")
|
||||
{
|
||||
int token = 0;
|
||||
pthread_t thread;
|
||||
void *result = NULL;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(0, pthread_create(&thread, NULL, join_notification_worker, &token));
|
||||
// A library may already have notified this task for an unrelated purpose.
|
||||
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
|
||||
TEST_ASSERT_EQUAL_INT(0, pthread_join(thread, &result));
|
||||
TEST_ASSERT_EQUAL_PTR(&token, result);
|
||||
ulTaskNotifyTake(pdTRUE, 0);
|
||||
}
|
||||
|
||||
static void *waiting_thread(void *arg)
|
||||
{
|
||||
TaskHandle_t *task_handle = (TaskHandle_t *)arg;
|
||||
|
||||
Reference in New Issue
Block a user