Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-97015

ASIOReactorTimer set after Reactor shutdown will never fire

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • 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(); }

      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:
            Unassigned Unassigned
            Reporter:
            erin.mcnulty@mongodb.com Erin McNulty
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: