util: keep Scheduler running if a callback throws

refs #3722

Change-Id: Icf19e1a59d67e351b210a60079b27b9b0a06fae6
diff --git a/src/util/scheduler.cpp b/src/util/scheduler.cpp
index 536061c..15200c9 100644
--- a/src/util/scheduler.cpp
+++ b/src/util/scheduler.cpp
@@ -19,9 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#include "common.hpp"
-
 #include "scheduler.hpp"
+#include <boost/scope_exit.hpp>
 
 namespace ndn {
 namespace util {
@@ -140,6 +139,11 @@
 
   m_isEventExecuting = true;
 
+  BOOST_SCOPE_EXIT_ALL(this) {
+    m_isEventExecuting = false;
+    this->scheduleNext();
+  };
+
   // process all expired events
   time::steady_clock::TimePoint now = time::steady_clock::now();
   while (!m_queue.empty()) {
@@ -153,9 +157,6 @@
     info->isExpired = true;
     info->callback();
   }
-
-  m_isEventExecuting = false;
-  this->scheduleNext();
 }
 
 } // namespace scheduler
diff --git a/src/util/scheduler.hpp b/src/util/scheduler.hpp
index c908ec0..cad5c09 100644
--- a/src/util/scheduler.hpp
+++ b/src/util/scheduler.hpp
@@ -137,7 +137,7 @@
 
   /**
    * \brief Schedule a one-time event after the specified delay
-   * \returns EventId that can be used to cancel the scheduled event
+   * \return EventId that can be used to cancel the scheduled event
    */
   EventId
   scheduleEvent(const time::nanoseconds& after, const EventCallback& callback);
@@ -161,6 +161,12 @@
   void
   scheduleNext();
 
+  /**
+   * \brief Execute expired events
+   * \note If an event callback throws, the exception is propagated to the thread running the
+   *       io_service. In case there are other expired events, they will be processed in the next
+   *       invocation of this method.
+   */
   void
   executeEvent(const boost::system::error_code& code);