--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,6 +18,7 @@
 #include <signal.h>
 #include <time.h>
 #include <thread>
+#include <atomic>
 
 #if defined(HAVE_LIBSSL) && defined(HAVE_PTHREAD) && \
     (!defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100004)
@@ -177,10 +178,11 @@
         sigset_t signals;
         sigfillset(&signals);
         pthread_sigmask(SIG_SETMASK, &signals, nullptr);
+        m_thread_cancel.test_and_set();
         m_thread = std::thread([=]() { HandleSignals(pZNC); });
     }
     ~CSignalHandler() {
-        pthread_cancel(m_thread.native_handle());
+        m_thread_cancel.clear();
         m_thread.join();
     }
 
@@ -216,11 +218,10 @@
         pthread_sigmask(SIG_SETMASK, &signals, nullptr);
         while (true) {
             int sig;
-            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr);
+            if (!m_thread_cancel.test_and_set()) pthread_exit(nullptr);
             // This thread can be cancelled, but only during this function.
             // Such cancel will be the only way to finish this thread.
             if (sigwait(&signals, &sig) == -1) continue;
-            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, nullptr);
             // TODO probably move switch() to CSignalHandlerMonitorFD?
             switch (sig) {
                 case SIGHUP:
@@ -259,6 +260,7 @@
     }
 
     std::thread m_thread;
+    std::atomic_flag m_thread_cancel;
 
     // pipe for waking up the main thread
     int m_iPipe[2];
