[zeromq-dev] [PATCH] Fix potential race when terminating io threads in ctx_t destructor.

Martin Townsend martin.townsend at xsilon.com
Wed Jul 2 11:05:27 CEST 2014


After stopping the IO threads wait for the associated poller to stop 
before destroying them to avoid get_load () == 0 assertion.
Potentially a fix for Issue #795

---
  src/ctx.cpp       | 12 ++++++++++--
  src/epoll.cpp     | 20 +++++++++++++++++++-
  src/epoll.hpp     |  4 ++++
  src/io_thread.cpp |  5 +++++
  src/io_thread.hpp |  3 +++
  5 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/src/ctx.cpp b/src/ctx.cpp
index 0155ef2..72db140 100644
--- a/src/ctx.cpp
+++ b/src/ctx.cpp
@@ -80,8 +80,16 @@ zmq::ctx_t::~ctx_t ()
          io_threads [i]->stop ();

      //  Wait till I/O threads actually terminate.
-    for (io_threads_t::size_type i = 0; i != io_threads.size (); i++)
-        delete io_threads [i];
+    for (io_threads_t::size_type i = 0; i != io_threads.size (); i++) {
+        int j = 0;
+
+        while (!io_threads [i]->stopped ()) {
+            sleep (1);
+            if (++j == 5)
+                break;
+        }
+        delete io_threads [i];
+    }

      //  Deallocate the reaper thread object.
      delete reaper;
diff --git a/src/epoll.cpp b/src/epoll.cpp
index 324d4bd..2c3a1b9 100644
--- a/src/epoll.cpp
+++ b/src/epoll.cpp
@@ -33,7 +33,8 @@
  #include "i_poll_events.hpp"

  zmq::epoll_t::epoll_t () :
-    stopping (false)
+    stopping (false),
+    poller_running (false)
  {
      epoll_fd = epoll_create (1);
      errno_assert (epoll_fd != -1);
@@ -41,12 +42,22 @@ zmq::epoll_t::epoll_t () :

  zmq::epoll_t::~epoll_t ()
  {
+    int i;
+
      //  Wait till the worker thread exits.
      worker.stop ();

      close (epoll_fd);
      for (retired_t::iterator it = retired.begin (); it != retired.end 
(); ++it)
          delete *it;
+
+    // Allow 5 seconds for the poller worker thread to exit.
+    i = 0;
+    while (poller_running) {
+        sleep (1);
+        if (++i == 5)
+            break;
+    }
  }

  zmq::epoll_t::handle_t zmq::epoll_t::add_fd (fd_t fd_, i_poll_events 
*events_)
@@ -126,6 +137,11 @@ void zmq::epoll_t::stop ()
      stopping = true;
  }

+bool zmq::epoll_t::stopped ()
+{
+    return !poller_running;
+}
+
  int zmq::epoll_t::max_fds ()
  {
      return -1;
@@ -135,6 +151,7 @@ void zmq::epoll_t::loop ()
  {
      epoll_event ev_buf [max_io_events];

+    poller_running = true;
      while (!stopping) {

          //  Execute any due timers.
@@ -171,6 +188,7 @@ void zmq::epoll_t::loop ()
              delete *it;
          retired.clear ();
      }
+    poller_running = false;
  }

  void zmq::epoll_t::worker_routine (void *arg_)
diff --git a/src/epoll.hpp b/src/epoll.hpp
index fbf871c..4a29c48 100644
--- a/src/epoll.hpp
+++ b/src/epoll.hpp
@@ -57,6 +57,7 @@ namespace zmq
          void reset_pollout (handle_t handle_);
          void start ();
          void stop ();
+        bool stopped ();

          static int max_fds ();

@@ -85,6 +86,9 @@ namespace zmq
          //  If true, thread is in the process of shutting down.
          bool stopping;

+        //  If true, poller worker thread is running.
+        bool poller_running;
+
          //  Handle of the physical thread doing the I/O work.
          thread_t worker;

diff --git a/src/io_thread.cpp b/src/io_thread.cpp
index b05b56b..59295a0 100644
--- a/src/io_thread.cpp
+++ b/src/io_thread.cpp
@@ -50,6 +50,11 @@ void zmq::io_thread_t::stop ()
      send_stop ();
  }

+bool zmq::io_thread_t::stopped ()
+{
+    return poller->stopped ();
+}
+
  zmq::mailbox_t *zmq::io_thread_t::get_mailbox ()
  {
      return &mailbox;
diff --git a/src/io_thread.hpp b/src/io_thread.hpp
index 49a2e80..e4c7797 100644
--- a/src/io_thread.hpp
+++ b/src/io_thread.hpp
@@ -52,6 +52,9 @@ namespace zmq
          //  Ask underlying thread to stop.
          void stop ();

+        //  Has it stopped, used after calling stop above.
+        bool stopped ();
+
          //  Returns mailbox associated with this I/O thread.
          mailbox_t *get_mailbox ();

-- 
1.9.1




More information about the zeromq-dev mailing list