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; }
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; }