Skip to content

Commit 14f5647

Browse files
authored
Merge pull request #2643 from c1728p9/fix_thread_self_termination
Fix thread self termination
2 parents 5ba3ab7 + abbd71d commit 14f5647

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

TESTS/mbedmicro-rtos-mbed/threads/main.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ void increment_with_murder(counter_t* counter) {
5959
(*counter)++;
6060
}
6161

62+
void self_terminate(Thread *self) {
63+
self->terminate();
64+
// Code should not get here
65+
TEST_ASSERT(0);
66+
}
67+
6268
// Tests that spawn tasks in different configurations
6369
template <void (*F)(counter_t *)>
6470
void test_single_thread() {
@@ -97,6 +103,13 @@ void test_serial_threads() {
97103
TEST_ASSERT_EQUAL(counter, N);
98104
}
99105

106+
void test_self_terminate() {
107+
Thread *thread = new Thread(osPriorityNormal, STACK_SIZE);
108+
thread->start(thread, self_terminate);
109+
thread->join();
110+
delete thread;
111+
}
112+
100113
utest::v1::status_t test_setup(const size_t number_of_cases) {
101114
GREENTEA_SETUP(40, "default_auto");
102115
return verbose_test_setup_handler(number_of_cases);
@@ -123,6 +136,8 @@ Case cases[] = {
123136
Case("Testing single thread with murder", test_single_thread<increment_with_murder>),
124137
Case("Testing parallel threads with murder", test_parallel_threads<3, increment_with_murder>),
125138
Case("Testing serial threads with murder", test_serial_threads<10, increment_with_murder>),
139+
140+
Case("Testing thread self terminate", test_self_terminate),
126141
};
127142

128143
Specification specification(test_setup, cases);

rtos/rtos/Thread.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,14 @@ osStatus Thread::terminate() {
101101
osStatus ret;
102102
_mutex.lock();
103103

104-
ret = osThreadTerminate(_tid);
104+
// Set the Thread's tid to NULL and
105+
// release the semaphore before terminating
106+
// since this thread could be terminating itself
107+
osThreadId local_id = _tid;
108+
_join_sem.release();
105109
_tid = (osThreadId)NULL;
106110

107-
// Wake threads joining the terminated thread
108-
_join_sem.release();
111+
ret = osThreadTerminate(local_id);
109112

110113
_mutex.unlock();
111114
return ret;
@@ -116,6 +119,14 @@ osStatus Thread::join() {
116119
if (ret < 0) {
117120
return osErrorOS;
118121
}
122+
123+
// The semaphore has been released so this thread is being
124+
// terminated or has been terminated. Once the mutex has
125+
// been locked it is ensured that the thread is deleted.
126+
_mutex.lock();
127+
MBED_ASSERT(NULL == _tid);
128+
_mutex.unlock();
129+
119130
// Release sem so any other threads joining this thread wake up
120131
_join_sem.release();
121132
return osOK;

0 commit comments

Comments
 (0)