From d816578e3a1ccf4aacb9f5a579fb0353cf889606 Mon Sep 17 00:00:00 2001 From: Anurag Kar Date: Thu, 27 Dec 2018 18:32:14 +0530 Subject: [PATCH 1/2] bugfix/pthread : pthread_detach implementation fixed to correctly delete pthread object when invoked after task completion --- components/pthread/pthread.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/components/pthread/pthread.c b/components/pthread/pthread.c index 1baa035c9b..a1ae6d440e 100644 --- a/components/pthread/pthread.c +++ b/components/pthread/pthread.c @@ -395,8 +395,19 @@ int pthread_detach(pthread_t thread) TaskHandle_t handle = pthread_find_handle(thread); if (!handle) { ret = ESRCH; - } else { + } else if (pthread->detached) { + // already detached + ret = EINVAL; + } else if (pthread->join_task) { + // already have waiting task to join + ret = EINVAL; + } else if (pthread->state == PTHREAD_TASK_STATE_RUN) { + // pthread still running pthread->detached = true; + } else { + // pthread already stopped + pthread_delete(pthread); + vTaskDelete(handle); } xSemaphoreGive(s_threads_mux); ESP_LOGV(TAG, "%s %p EXIT %d", __FUNCTION__, pthread, ret); From f5e8e052821a827dfe659a33b5ea3fedd209b20d Mon Sep 17 00:00:00 2001 From: Anurag Kar Date: Fri, 28 Dec 2018 14:41:24 +0530 Subject: [PATCH 2/2] pthread tests : test case added for detach functionality --- components/pthread/test/test_pthread.c | 69 ++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/components/pthread/test/test_pthread.c b/components/pthread/test/test_pthread.c index 543fbf5858..7453f7a75a 100644 --- a/components/pthread/test/test_pthread.c +++ b/components/pthread/test/test_pthread.c @@ -60,6 +60,75 @@ TEST_CASE("pthread create join", "[pthread]") } } +static void *waiting_thread(void *arg) +{ + TaskHandle_t *task_handle = (TaskHandle_t *)arg; + TaskHandle_t parent_task = *task_handle; + + *task_handle = xTaskGetCurrentTaskHandle(); + + xTaskNotify(parent_task, 0, eNoAction); + xTaskNotifyWait(0, 0, NULL, portMAX_DELAY); + return NULL; +} + +TEST_CASE("pthread detach", "[pthread]") +{ + int res = 0; + pthread_t new_thread = (pthread_t)NULL; + TaskHandle_t task_handle = NULL; + const int task_count = uxTaskGetNumberOfTasks(); + bool detach_works = false; + + if (TEST_PROTECT()) { + task_handle = xTaskGetCurrentTaskHandle(); + res = pthread_create(&new_thread, NULL, waiting_thread, (void *)&task_handle); + TEST_ASSERT_EQUAL_INT(0, res); + + res = xTaskNotifyWait(0, 0, NULL, 100 / portTICK_PERIOD_MS); + TEST_ASSERT_EQUAL_INT(pdTRUE, res); + + xTaskNotify(task_handle, 0, eNoAction); + vTaskDelay(100 / portTICK_PERIOD_MS); + + res = pthread_detach(new_thread); + TEST_ASSERT_EQUAL_INT(0, res); + + res = uxTaskGetNumberOfTasks(); + TEST_ASSERT_EQUAL_INT(task_count, res); + detach_works = true; + } + + if (!detach_works) { + vTaskDelete(task_handle); + } else { + detach_works = false; + } + + if (TEST_PROTECT()) { + task_handle = xTaskGetCurrentTaskHandle(); + res = pthread_create(&new_thread, NULL, waiting_thread, (void *)&task_handle); + TEST_ASSERT_EQUAL_INT(0, res); + + res = xTaskNotifyWait(0, 0, NULL, 100 / portTICK_PERIOD_MS); + TEST_ASSERT_EQUAL_INT(pdTRUE, res); + + res = pthread_detach(new_thread); + TEST_ASSERT_EQUAL_INT(0, res); + + xTaskNotify(task_handle, 0, eNoAction); + vTaskDelay(100 / portTICK_PERIOD_MS); + + res = uxTaskGetNumberOfTasks(); + TEST_ASSERT_EQUAL_INT(task_count, res); + detach_works = true; + } + + if (!detach_works) { + vTaskDelete(task_handle); + } +} + TEST_CASE("pthread attr init destroy", "[pthread]") { int res = 0;