title: Cancelling boost asio deadline timer safely
body: <p>I'm trying to cancel a <code>boost::asio::basic_waitable_timer&lt;std::chrono::steady_clock&gt;</code> safely.</p>
  
  <p>According to this <a href="https://stackoverflow.com/questions/29047765/atomically-cancel-asio-asynchronious-timer-from-another-thread">answer</a>, this code should do that work:</p>
  
  <pre><code>timer.get_io_service().post([&amp;]{timer.cancel();})
  </code></pre>
  
  <p>I'm afraid it doesn't work for me.<br>
  Am I doing something wrong?<br>
  This is my code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include "boost/asio.hpp"
  #include &lt;chrono&gt;
  #include &lt;thread&gt;
  #include &lt;random&gt;
  
  boost::asio::io_service io_service;
  boost::asio::basic_waitable_timer&lt;std::chrono::steady_clock&gt; timer(io_service);
  std::atomic&lt;bool&gt; started;
  
  void handle_timeout(const boost::system::error_code&amp; ec)
  {
      if (!ec) {
          started = true;
          std::cerr &lt;&lt; "tid: " &lt;&lt; std::this_thread::get_id() &lt;&lt; ", handle_timeout\n";
          timer.expires_from_now(std::chrono::milliseconds(10));
          timer.async_wait(&amp;handle_timeout);
      } else if (ec == boost::asio::error::operation_aborted) {
          std::cerr &lt;&lt; "tid: " &lt;&lt; std::this_thread::get_id() &lt;&lt; ", handle_timeout aborted\n";
      } else {
          std::cerr &lt;&lt; "tid: " &lt;&lt; std::this_thread::get_id() &lt;&lt; ", handle_timeout another error\n";
      }
  }
  
  int main() {
  
      std::cout &lt;&lt; "tid: " &lt;&lt; std::this_thread::get_id() &lt;&lt; ", Hello, World!" &lt;&lt; std::endl;
      std::random_device rd;
      std::mt19937 gen(rd());
      std::uniform_int_distribution&lt;&gt; dis(1, 100);
  
      for (auto i = 0; i &lt; 1000; i++) {
  
          started = false;
          std::thread t([&amp;](){
  
              timer.expires_from_now(std::chrono::milliseconds(0));
              timer.async_wait(&amp;handle_timeout);
  
              io_service.run();
          });
  
          while (!started) {};
          auto sleep = dis(gen);
          std::cout &lt;&lt; "tid: " &lt;&lt; std::this_thread::get_id() &lt;&lt; ", i: " &lt;&lt; i &lt;&lt; ", sleeps for " &lt;&lt; sleep &lt;&lt; " [ms]" &lt;&lt; std::endl;
          std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
          timer.get_io_service().post([](){
              std::cerr &lt;&lt; "tid: " &lt;&lt; std::this_thread::get_id() &lt;&lt; ", cancelling in post\n";
              timer.cancel();
          });
  //      timer.cancel();
          std::cout &lt;&lt; "tid: " &lt;&lt; std::this_thread::get_id() &lt;&lt; ", i: " &lt;&lt; i &lt;&lt; ", waiting for thread to join()" &lt;&lt; std::endl;
          t.join();
          io_service.reset();
      }
  
      return 0;
  }
  </code></pre>
  
  <p>This is the output:</p>
  
  <blockquote>
    <p>...<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737353967488, i: 2, waiting for thread to join()<br>
    tid: 140737335076608, cancelling in post<br>
    tid: 140737335076608, handle_timeout aborted<br>
    tid: 140737353967488, i: 3, sleeps for 21 [ms]<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737353967488, i: 3, waiting for thread to join()<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737335076608, cancelling in post<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737335076608, handle_timeout<br>
    tid: 140737335076608, handle_timeout<br>
    ...<br>
    continue forever...  </p>
  </blockquote>
  
  <p>As you can see, the <code>timer.cancel()</code> is being called from the appropriate thread:  </p>
  
  <blockquote>
    <p>tid: 140737335076608, cancelling in post  </p>
  </blockquote>
  
  <p>BUT there's no </p>
  
  <blockquote>
    <p>tid: 140737335076608, handle_timeout aborted  </p>
  </blockquote>
  
  <p>Afterwards.  </p>
  
  <p>Main waits forever.</p>