fix(pthread): wait for child exit after unrelated notifications

This commit is contained in:
n-IA-hane
2026-10-07 09:08:49 +05:30
committed by Meet Patel
parent ce2100de51
commit 602fdf5e5a
2 changed files with 31 additions and 5 deletions
+10 -5
View File
@@ -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;