Ejemplo n.º 1
0
void LibEventServer::stop() {
  Lock lock(m_mutex);
  if (getStatus() != RunStatus::RUNNING || m_server == nullptr) return;

#define SHUT_FBLISTEN 3
  /*
   * Modifications to the Linux kernel to support shutting down a listen
   * socket for new connections only, but anything which has completed
   * the TCP handshake will still be accepted.  This allows for un-accepted
   * connections to be queued and then wait until all queued requests are
   * actively being processed.
   */
  if (RuntimeOption::ServerShutdownListenWait > 0 &&
      m_accept_sock != -1 && shutdown(m_accept_sock, SHUT_FBLISTEN) == 0) {
    int noWorkCount = 0;
    for (int i = 0; i < RuntimeOption::ServerShutdownListenWait; i++) {
      // Give the acceptor thread time to clean out all requests
      Logger::Info(
          "LibEventServer stopping port %d: [%d/%d] a/q/e %d/%d/%d",
          m_port, i, RuntimeOption::ServerShutdownListenWait,
          getActiveWorker(), getQueuedJobs(), getLibEventConnectionCount());
      sleep(1);

      // If we're not doing anything, break out quickly
      noWorkCount += (getQueuedJobs() == 0 && getActiveWorker() == 0);
      if (RuntimeOption::ServerShutdownListenNoWork > 0 &&
          noWorkCount >= RuntimeOption::ServerShutdownListenNoWork)
        break;
      if (getLibEventConnectionCount() == 0 &&
          getQueuedJobs() == 0 && getActiveWorker() == 0)
        break;
    }
    Logger::Info("LibEventServer stopped port %d: a/q/e %d/%d/%d",
        m_port, getActiveWorker(), getQueuedJobs(),
        getLibEventConnectionCount());
  }

  // inform LibEventServer::onRequest() to stop queuing
  setStatus(RunStatus::STOPPING);

  // stop JobQueue processing
  m_dispatcher.stop();

  // stop event loop
  setStatus(RunStatus::STOPPED);
  if (write(m_pipeStop.getIn(), "", 1) < 0) {
    // an error occured but we're in shutdown already, so ignore
  }
  m_dispatcherThread.waitForEnd();

  // wait for the timeout thread to stop
  m_timeoutThreadData.stop();
  m_timeoutThread.waitForEnd();

  evhttp_free(m_server);
  m_server = nullptr;
}
Ejemplo n.º 2
0
void ProxygenServer::forceStop() {
  Logger::Info("%p: forceStop ProxygenServer port=%d, enqueued=%d, conns=%d",
               this, m_port, m_enqueuedCount, getLibEventConnectionCount());
  m_httpServerSocket.reset();
  m_httpsServerSocket.reset();

  // Drops all open connections
  if (m_httpAcceptor && m_httpAcceptor->getState() < Acceptor::State::kDone) {
    m_httpAcceptor->forceStop();
  }
  if (m_httpsAcceptor && m_httpAcceptor->getState() < Acceptor::State::kDone) {
    m_httpsAcceptor->forceStop();
  }

  // No more responses coming from worker threads
  stopConsuming();
  Logger::Verbose("%p: Stopped response queue consumer port=%d", this, m_port);

  // The worker should exit gracefully
  m_worker.stopWhenIdle();
  Logger::Verbose("%p: i/o thread notified to stop port=%d", this, m_port);

  // Aaaand we're done - oops not thread safe.  Does it matter?
  setStatus(RunStatus::STOPPED);

  HttpServer::MarkShutdownStat(ShutdownEvent::SHUTDOWN_DONE);

  for (auto listener: m_listeners) {
    listener->serverStopped(this);
  }
}
Ejemplo n.º 3
0
void ProxygenServer::timeoutExpired() noexcept {
  Logger::Info("%p: shutdown timer expired for ProxygenServer port=%d, "
               "state=%d, a/q/e %d/%d/%d", this, m_port, (int)m_shutdownState,
               getActiveWorker(), getQueuedJobs(),
               getLibEventConnectionCount());
  // proceed to next shutdown phase
  doShutdown();
}
Ejemplo n.º 4
0
void ProxygenServer::reportShutdownStatus() {
  if (m_port != RuntimeOption::ServerPort) return;
  if (getStatus() == RunStatus::STOPPED) return;
  Logger::FInfo("Shutdown state={}, a/q/e/p {}/{}/{}/{}, RSS={}Mb",
                static_cast<int>(m_shutdownState),
                getActiveWorker(),
                getQueuedJobs(),
                getLibEventConnectionCount(),
                m_pendingTransports.size(),
                Process::GetProcessRSS(getpid()));
  m_worker.getEventBase()->runAfterDelay([this]{reportShutdownStatus();}, 500);
}
Ejemplo n.º 5
0
void ProxygenServer::stopVM() {
  m_shutdownState = ShutdownState::STOPPING_VM;
  // we can't call m_dispatcher.stop() from the event loop, because it blocks
  // all I/O.  Spawn a thread to call it and callback when it's done.
  std::thread vmStopper([this] {
      purge_all();
      Logger::Info("%p: Stopping dispatcher port=%d", this, m_port);
      m_dispatcher.stop();
      Logger::Info("%p: Dispatcher stopped port=%d.  conns=%d", this, m_port,
                   getLibEventConnectionCount());
      m_worker.getEventBase()->runInEventBaseThread([this] {
          vmStopped();
        });
    });
  vmStopper.detach();
}
Ejemplo n.º 6
0
bool ProxygenServer::canAccept() {
  return (RuntimeOption::ServerConnectionLimit == 0 ||
          getLibEventConnectionCount() < RuntimeOption::ServerConnectionLimit);
}