Browse Source

Safe thread join

Kajetan Johannes Hammerle 3 weeks ago
parent
commit
cfe5f7b284
7 changed files with 39 additions and 2 deletions
  1. 2 0
      CMakeLists.txt
  2. 8 0
      include/core/Thread.h
  3. 1 0
      src/ErrorSimulator.c
  4. 3 0
      src/ErrorSimulator.h
  5. 2 2
      src/ReadLine.c
  6. 18 0
      src/Thread.c
  7. 5 0
      test/modules/ReadLineTests.c

+ 2 - 0
CMakeLists.txt

@@ -17,6 +17,7 @@ set(SRC
     "src/ReadLine.c"
     "src/SpinLock.c"
     "src/Test.c"
+    "src/Thread.c"
     "src/ToString.c"
     "src/Utility.c"
     "src/Vector.c"
@@ -108,6 +109,7 @@ target_sources(core PUBLIC
         ./include/core/ReadLine.h
         ./include/core/SpinLock.h
         ./include/core/Test.h
+        ./include/core/Thread.h
         ./include/core/ToString.h
         ./include/core/Types.h
         ./include/core/Utility.h

+ 8 - 0
include/core/Thread.h

@@ -0,0 +1,8 @@
+#ifndef CORE_THREAD_H
+#define CORE_THREAD_H
+
+#include <threads.h>
+
+bool joinThreadSafe(thrd_t* t);
+
+#endif

+ 1 - 0
src/ErrorSimulator.c

@@ -5,6 +5,7 @@
 bool failFileClose = false;
 bool failTimeGet = false;
 bool failThreadInit = false;
+bool failThreadJoin = false;
 bool failMutexInit = false;
 bool failMutexLock = false;
 bool failMutexUnlock = false;

+ 3 - 0
src/ErrorSimulator.h

@@ -5,12 +5,14 @@
 extern bool failFileClose;
 extern bool failTimeGet;
 extern bool failThreadInit;
+extern bool failThreadJoin;
 extern bool failMutexInit;
 extern bool failMutexLock;
 extern bool failMutexUnlock;
 #define FILE_CLOSE_FAIL failFile
 #define TIME_GET_FAIL failTimeGet
 #define THREAD_INIT_FAIL failThreadInit
+#define THREAD_JOIN_FAIL failThreadJoin
 #define MUTEX_INIT_FAIL failMutexInit
 #define MUTEX_LOCK_FAIL failMutexLock
 #define MUTEX_UNLOCK_FAIL failMutexUnlock
@@ -18,6 +20,7 @@ extern bool failMutexUnlock;
 #define FILE_CLOSE_FAIL false
 #define TIME_GET_FAIL false
 #define THREAD_INIT_FAIL false
+#define THREAD_JOIN_FAIL false
 #define MUTEX_INIT_FAIL false
 #define MUTEX_LOCK_FAIL false
 #define MUTEX_UNLOCK_FAIL false

+ 2 - 2
src/ReadLine.c

@@ -7,12 +7,12 @@
 #include <stdio.h>
 #include <string.h>
 #include <termios.h>
-#include <threads.h>
 #include <unistd.h>
 
 #include "ErrorSimulator.h"
 #include "core/Logger.h"
 #include "core/Queue.h"
+#include "core/Thread.h"
 
 #define HISTORY_LENGTH 10
 #define CONSOLE_BUFFER_SIZE 256
@@ -290,7 +290,7 @@ bool readLine(char* buffer_, size_t n) {
 
 void stopReadLine() {
     atomic_store(&running, false);
-    thrd_join(readThread, nullptr);
+    joinThreadSafe(&readThread);
     restoreAttributes();
     destroyQueueCL(&buffer);
     mtx_destroy(&bufferMutex);

+ 18 - 0
src/Thread.c

@@ -0,0 +1,18 @@
+#include "core/Thread.h"
+
+#include <string.h>
+
+#include "ErrorSimulator.h"
+#include "core/Logger.h"
+
+bool joinThreadSafe(thrd_t* t) {
+    static thrd_t nullThread = {0};
+    if(memcmp(t, &nullThread, sizeof(thrd_t)) != 0) {
+        if(THREAD_JOIN_FAIL || thrd_join(*t, nullptr) != thrd_success) {
+            LOG_ERROR("cannot join thread");
+            return true;
+        }
+        *t = (thrd_t){0};
+    }
+    return false;
+}

+ 5 - 0
test/modules/ReadLineTests.c

@@ -77,5 +77,10 @@ void testReadLine(void) {
         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb");
     testStringError(__LINE__, "abäo");
     testStringError(__LINE__, "bäöo");
+#ifdef ERROR_SIMULATOR
+    failThreadJoin = true;
+    stopReadLine();
+    failThreadJoin = false;
+#endif
     stopReadLine();
 }