From 4668ff59e5cc6bdd52db800801a726f12357196b Mon Sep 17 00:00:00 2001
From: Cameron Gutman <aicommander@gmail.com>
Date: Fri, 28 Apr 2023 00:08:44 -0500
Subject: [PATCH] Fix ringing with non-truthy values in alarm_t

The Windows mDNS registration code does this in the failure path and ends up deadlocking.
---
 src/thread_safe.h | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/thread_safe.h b/src/thread_safe.h
index 6db1e9ec..f69f0a5b 100644
--- a/src/thread_safe.h
+++ b/src/thread_safe.h
@@ -141,14 +141,12 @@ namespace safe {
   public:
     using status_t = util::optional_t<T>;
 
-    alarm_raw_t():
-        _status { util::false_v<status_t> } {}
-
     void
     ring(const status_t &status) {
       std::lock_guard lg(_lock);
 
       _status = status;
+      _rang = true;
       _cv.notify_one();
     }
 
@@ -157,6 +155,7 @@ namespace safe {
       std::lock_guard lg(_lock);
 
       _status = std::move(status);
+      _rang = true;
       _cv.notify_one();
     }
 
@@ -165,7 +164,7 @@ namespace safe {
     wait_for(const std::chrono::duration<Rep, Period> &rel_time) {
       std::unique_lock ul(_lock);
 
-      return _cv.wait_for(ul, rel_time, [this]() { return (bool) status(); });
+      return _cv.wait_for(ul, rel_time, [this]() { return _rang; });
     }
 
     template <class Rep, class Period, class Pred>
@@ -173,7 +172,7 @@ namespace safe {
     wait_for(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
       std::unique_lock ul(_lock);
 
-      return _cv.wait_for(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); });
+      return _cv.wait_for(ul, rel_time, [this, &pred]() { return _rang || pred(); });
     }
 
     template <class Rep, class Period>
@@ -181,7 +180,7 @@ namespace safe {
     wait_until(const std::chrono::duration<Rep, Period> &rel_time) {
       std::unique_lock ul(_lock);
 
-      return _cv.wait_until(ul, rel_time, [this]() { return (bool) status(); });
+      return _cv.wait_until(ul, rel_time, [this]() { return _rang; });
     }
 
     template <class Rep, class Period, class Pred>
@@ -189,20 +188,20 @@ namespace safe {
     wait_until(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
       std::unique_lock ul(_lock);
 
-      return _cv.wait_until(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); });
+      return _cv.wait_until(ul, rel_time, [this, &pred]() { return _rang || pred(); });
     }
 
     auto
     wait() {
       std::unique_lock ul(_lock);
-      _cv.wait(ul, [this]() { return (bool) status(); });
+      _cv.wait(ul, [this]() { return _rang; });
     }
 
     template <class Pred>
     auto
     wait(Pred &&pred) {
       std::unique_lock ul(_lock);
-      _cv.wait(ul, [this, &pred]() { return (bool) status() || pred(); });
+      _cv.wait(ul, [this, &pred]() { return _rang || pred(); });
     }
 
     const status_t &
@@ -218,13 +217,15 @@ namespace safe {
     void
     reset() {
       _status = status_t {};
+      _rang = false;
     }
 
   private:
     std::mutex _lock;
     std::condition_variable _cv;
 
-    status_t _status;
+    status_t _status { util::false_v<status_t> };
+    bool _rang { false };
   };
 
   template <class T>