Example #1
0
  bool SchedulerBase::Run()
  {
    uint32_t iter=0;
    TimeSpec timeout;
    TimeSpec immediate;
    bool gotEvents;

    if (!LogVerify(IsMainThread()))
      return false;

    m_isStarted = true;

    // Start with a quick event check.
    timeout = immediate;
    while (true)
    {
      iter++;

      if (m_wantsShutdown)
        break;

      // 
      //  Get event, or timeout. 
      // 
      gLog.Optional(Log::TimerDetail, "checking events (%u)", iter);
      gotEvents = waitForEvents(timeout);

      // By default the next event check is immediately.
      timeout = immediate;  

      // 
      // High priority timers, if any, get handled now 
      // 
      while (!m_wantsShutdown && expireTimer(Timer::Priority::Hi))
      { //nothing
      }

      if (m_wantsShutdown)
        break;

      // 
      //  Handle any events.
      // 
      if (gotEvents)
      {
        int socketId;

        gLog.Optional(Log::TimerDetail, "Handling events (%u)", iter);


        while (-1 != (socketId = getNextSocketEvent()))
        {
          // we have a socket event .. is it a socket or a signal?

          SocketItemHashMap::iterator foundSocket;
          SignalItemHashMap::iterator foundSignal;

          if (m_sockets.end() != (foundSocket = m_sockets.find(socketId)))
          {
            if (LogVerify(foundSocket->second.callback != NULL))
              foundSocket->second.callback(socketId, foundSocket->second.userdata);
          }
          else if (m_signals.end() != (foundSignal = m_signals.find(socketId)))
          {
            if (LogVerify(foundSignal->second.callback != NULL))
            {
              // 'Drain' the pipe.
              char drain[128];
              int result;
              size_t reads = 0;

              while ( 0 < (result = ::read(socketId, drain, sizeof(drain))))
                reads++;

              if (reads == 0 && result < 0)
                gLog.LogError("Failed to read from pipe %d: %s", socketId, strerror(errno));
              else if (result == 0)
                gLog.LogError("Signaling pipe write end for %d closed", socketId);

              foundSignal->second.callback(foundSignal->second.fdWrite, foundSignal->second.userdata);
            }
          }
          else
          {
            gLog.Optional(Log::TimerDetail, "Socket (%d) signaled with no handler (%u).", socketId, iter);
          }

          if (m_wantsShutdown)
            break;
        }

        if (m_wantsShutdown)
          break;
      }

      // 
      //  Handle a low priority timer if there are no events.
      //  TODO: starvation is a potential problem for low priority timers.
      // 
      if (!gotEvents && !expireTimer(Timer::Priority::Low))
      {
        // No events and no more timers, so we are ready to sleep again. 
        timeout = getNextTimerTimeout();
      }

      if (m_wantsShutdown)
        break;
    } // while true

    return true;
  }
Example #2
0
int main(int ac, char **av, char **envp)
{
	BinaryDir = GetFullProgDir(av[0]);
	if (BinaryDir[BinaryDir.length() - 1] == '.')
		BinaryDir = BinaryDir.substr(0, BinaryDir.length() - 2);

#ifdef _WIN32
	Anope::string::size_type n = BinaryDir.rfind('\\');
#else
	Anope::string::size_type n = BinaryDir.rfind('/');
#endif
	Anope::ServicesDir = BinaryDir.substr(0, n);

#ifdef _WIN32
	/* Clean out the module runtime directory prior to running, just in case files were left behind during a previous run */
	ModuleManager::CleanupRuntimeDirectory();

	OnStartup();
#endif

	try
	{
		/* General initialization first */
		Anope::Init(ac, av);
	}
	catch (const CoreException &ex)
	{
		Anope::Logger.Log(ex.GetReason());
		return -1;
	}

	try
	{
		Uplink::Connect();
	}
	catch (const SocketException &ex)
	{
		Anope::Logger.Terminal(_("Unable to connect to uplink #{0} ({1}:{2}): {3}"), Anope::CurrentUplink + 1, Config->Uplinks[Anope::CurrentUplink].host, Config->Uplinks[Anope::CurrentUplink].port, ex.GetReason());
	}

	/* Set up timers */
	time_t last_check = Anope::CurTime;
	ExpireTimer expireTimer(Config->GetBlock("options")->Get<time_t>("expiretimeout", "30m"));
	Uplink::PingTimer pingTimer(30);

	/*** Main loop. ***/
	while (!Anope::Quitting)
	{
		Anope::Logger.Debug2("Top of main loop");

		/* Process timers */
		if (Anope::CurTime - last_check >= Config->TimeoutCheck)
		{
			TimerManager::TickTimers(Anope::CurTime);
			last_check = Anope::CurTime;
		}

		/* Process the socket engine */
		SocketEngine::Process();

		if (Anope::Signal)
			Anope::HandleSignal();
	}

	if (Anope::Restarting)
	{
		EventManager::Get()->Dispatch(&Event::Restart::OnRestart);
	}
	else
	{
		EventManager::Get()->Dispatch(&Event::Shutdown::OnShutdown);
	}

	if (Anope::QuitReason.empty())
		Anope::QuitReason = "Terminating, reason unknown";
	Anope::Logger.Log(Anope::QuitReason);

	delete UplinkSock;

	ModuleManager::UnloadAll();
	SocketEngine::Shutdown();
	for (Module *m; (m = ModuleManager::FindFirstOf(PROTOCOL)) != NULL;)
		ModuleManager::UnloadModule(m, NULL);

#ifdef _WIN32
	ModuleManager::CleanupRuntimeDirectory();

	OnShutdown();
#endif

	if (Anope::Restarting)
	{
		chdir(BinaryDir.c_str());
		Anope::string sbin = "./" + Anope::ServicesBin;
		av[0] = const_cast<char *>(sbin.c_str());
		execve(Anope::ServicesBin.c_str(), av, envp);
		Anope::Logger.Log("Restart failed");
		Anope::ReturnValue = -1;
	}

	return Anope::ReturnValue;
}