ASIOReactorTimer set after Reactor shutdown will never fire

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Fixed
    • Priority: Major - P3
    • 8.2.0-rc0
    • Affects Version/s: None
    • Component/s: None
    • Networking & Observability
    • ALL
    • Hide
      TEST(AsioTransportLayer, UseTimerAfterReactorShutdown) {
          TestFixture tf;    
          Notification<void> shutdown;
          auto reactor = tf.tla().getReactor(TransportLayer::kNewReactor);
          auto timer = reactor->makeTimer();
          auto reactorThread = stdx::thread([reactor, &shutdown] {
              LOGV2(8703700, "running reactor");
              reactor->run();
              LOGV2(8703701, "reactor stopped, draining");
              reactor->drain();
              LOGV2(8703702, "reactor drain complete");
              shutdown.set();
          });    
      
          auto timer1 = timer->waitUntil(Date_t::now() + Seconds(5));
          std::move(timer1).get();
          LOGV2(8703704, "first timer fired");    
          
          LOGV2(8703704, "shutting down reactor");
          reactor->stop();
          shutdown.get();    
      
          LOGV2(8703704, "setting second timer");
          auto timer2 = timer->waitUntil(Date_t::now() + Seconds(5));
          std::move(timer2).get(); // hangs here
          LOGV2(8703704, "second timer fired");    
      
          reactorThread.join();
      } 
      Show
      TEST(AsioTransportLayer, UseTimerAfterReactorShutdown) {     TestFixture tf;    Notification<void> shutdown;     auto reactor = tf.tla().getReactor(TransportLayer::kNewReactor);     auto timer = reactor->makeTimer();     auto reactorThread = stdx::thread([reactor, &shutdown] {         LOGV2(8703700, "running reactor" );         reactor->run();         LOGV2(8703701, "reactor stopped, draining" );         reactor->drain();         LOGV2(8703702, "reactor drain complete" );         shutdown.set();     });    auto timer1 = timer->waitUntil(Date_t::now() + Seconds(5));     std::move(timer1).get();     LOGV2(8703704, "first timer fired" );    LOGV2(8703704, "shutting down reactor" );     reactor->stop();     shutdown.get();    LOGV2(8703704, "setting second timer" );     auto timer2 = timer->waitUntil(Date_t::now() + Seconds(5));     std::move(timer2).get(); // hangs here     LOGV2(8703704, "second timer fired" );    reactorThread.join(); }
    • N&O 2025-06-23, N&O 2025-07-07
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      If we set an ASIOReactorTimer after the corresponding reactor has been shutdown, the timer will never fire, which is non-obvious behavior based on the documentation of the class. We should consider setting the promise immediately with a 
      ErrorCodes::ShutdownInProgress error if a user sets a timer after the reactor has been shutdown rather than returning a future that will never be fulfilled.

            Assignee:
            Nicole Bain
            Reporter:
            Erin McNulty (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: