]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd.cpp
Extra error detection, thwap me if this comes up with false positives
[user/henk/code/inspircd.git] / src / inspircd.cpp
index c52444debaf9222779b513298c758ca10cfc36f5..9b7d6fa1786d1b131dc6492ea8b396c619149e9c 100644 (file)
@@ -26,6 +26,9 @@ using namespace std;
 #include <sys/ioctl.h>
 #include <time.h>
 #include <string>
+#include <exception>
+#include <stdexcept>
+#include <new>
 #ifdef GCC3
 #include <ext/hash_map>
 #else
@@ -71,7 +74,9 @@ std::vector<userrec*> local_users;
 
 extern int MODCOUNT;
 extern char LOG_FILE[MAXBUF];
-int openSockfd[MAXSOCKS];
+int openSockfd[MAX_DESCRIPTORS];
+int yield_depth;
+int iterations = 0;
 sockaddr_in client,server;
 socklen_t length;
 
@@ -89,7 +94,7 @@ ServerConfig *Config = new ServerConfig;
 
 user_hash clientlist;
 chan_hash chanlist;
-whowas_hash whowas;
+
 servernamelist servernames;
 char lowermap[255];
 
@@ -162,16 +167,20 @@ InspIRCd::InspIRCd(int argc, char** argv)
        if (argc > 1) {
                for (int i = 1; i < argc; i++)
                {
-                       if (!strcmp(argv[i],"-nofork")) {
+                       if (!strcmp(argv[i],"-nofork"))
+                       {
                                Config->nofork = true;
                        }
-                       if (!strcmp(argv[i],"-wait")) {
+                       if (!strcmp(argv[i],"-wait"))
+                       {
                                sleep(6);
                        }
-                       if (!strcmp(argv[i],"-nolimit")) {
-                               Config->unlimitcore = true;
+                       if (!strcmp(argv[i],"-nolimit"))
+                       {
+                               printf("WARNING: The `-nolimit' option is deprecated, and now on by default. This behaviour may change in the future.\n");
                        }
-                       if (!strcmp(argv[i],"-logfile")) {
+                       if (!strcmp(argv[i],"-logfile"))
+                       {
                                if (argc > i+1)
                                {
                                        strlcpy(LOG_FILE,argv[i+1],MAXBUF);
@@ -191,15 +200,15 @@ InspIRCd::InspIRCd(int argc, char** argv)
        this->MakeLowerMap();
 
         OpenLog(argv, argc);
+       this->stats = new serverstats();
         Config->ClearStack();
         Config->Read(true,NULL);
         CheckRoot();
        this->ModeGrok = new ModeParser();
        this->Parser = new CommandParser();
-       this->stats = new serverstats();
         AddServerName(Config->ServerName);
         CheckDie();
-        stats->BoundPortCount = BindPorts();
+        stats->BoundPortCount = BindPorts(true);
 
        for(int t = 0; t < 255; t++)
                Config->global_implementation[t] = 0;
@@ -210,7 +219,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
        SetSignals();
         if (!Config->nofork)
         {
-                if (DaemonSeed() == ERROR)
+               if (!DaemonSeed())
                 {
                         printf("ERROR: could not go into daemon mode. Shutting down.\n");
                         Exit(ERROR);
@@ -296,7 +305,6 @@ void InspIRCd::erase_module(int j)
 void InspIRCd::MoveTo(std::string modulename,int slot)
 {
        unsigned int v2 = 256;
-       log(DEBUG,"Moving %s to slot %d",modulename.c_str(),slot);
        for (unsigned int v = 0; v < Config->module_names.size(); v++)
        {
                if (Config->module_names[v] == modulename)
@@ -306,11 +314,7 @@ void InspIRCd::MoveTo(std::string modulename,int slot)
                        break;
                }
        }
-       if (v2 == (unsigned int)slot)
-       {
-               log(DEBUG,"Item %s already in slot %d!",modulename.c_str(),slot);
-       }
-       else if (v2 < 256)
+       if ((v2 != (unsigned int)slot) && (v2 < 256))
        {
                // Swap the module names over
                Config->module_names[v2] = Config->module_names[slot];
@@ -331,7 +335,6 @@ void InspIRCd::MoveTo(std::string modulename,int slot)
                        Config->implement_lists[v2][n] = Config->implement_lists[slot][n];
                        Config->implement_lists[slot][n] = x;
                }
-               log(DEBUG,"Moved %s to slot successfully",modulename.c_str());
        }
        else
        {
@@ -341,7 +344,6 @@ void InspIRCd::MoveTo(std::string modulename,int slot)
 
 void InspIRCd::MoveAfter(std::string modulename, std::string after)
 {
-       log(DEBUG,"Move %s after %s...",modulename.c_str(),after.c_str());
        for (unsigned int v = 0; v < Config->module_names.size(); v++)
        {
                if (Config->module_names[v] == after)
@@ -354,7 +356,6 @@ void InspIRCd::MoveAfter(std::string modulename, std::string after)
 
 void InspIRCd::MoveBefore(std::string modulename, std::string before)
 {
-       log(DEBUG,"Move %s before %s...",modulename.c_str(),before.c_str());
        for (unsigned int v = 0; v < Config->module_names.size(); v++)
        {
                if (Config->module_names[v] == before)
@@ -509,13 +510,7 @@ bool InspIRCd::LoadModule(const char* filename)
                                modules[MODCOUNT+1]->Implements(x);
 
                                for(int t = 0; t < 255; t++)
-                               {
                                        Config->global_implementation[t] += Config->implement_lists[MODCOUNT+1][t];
-                                       if (Config->implement_lists[MODCOUNT+1][t])
-                                       {
-                                               log(DEBUG,"Add global implementation: %d %d => %d",MODCOUNT+1,t,Config->global_implementation[t]);
-                                       }
-                               }
                        }
                        else
                        {
@@ -559,15 +554,11 @@ bool InspIRCd::LoadModule(const char* filename)
                }
                else if ((modules[j]->Prioritize() & 0xFF) == PRIORITY_BEFORE)
                {
-                       log(DEBUG,"Module %d wants PRIORITY_BEFORE",j);
                        put_before[Config->module_names[j]] = Config->module_names[modules[j]->Prioritize() >> 8];
-                       log(DEBUG,"Before: %s",Config->module_names[modules[j]->Prioritize() >> 8].c_str());
                }
                else if ((modules[j]->Prioritize() & 0xFF) == PRIORITY_AFTER)
                {
-                       log(DEBUG,"Module %d wants PRIORITY_AFTER",j);
                        put_after[Config->module_names[j]] = Config->module_names[modules[j]->Prioritize() >> 8];
-                       log(DEBUG,"After: %s",Config->module_names[modules[j]->Prioritize() >> 8].c_str());
                }
        }
        for (unsigned int j = 0; j < put_to_back.size(); j++)
@@ -602,6 +593,11 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
         sockaddr_in sock_us;     // our port number
         socklen_t uslen;         // length of our port number
 
+       if (yield_depth > 100)
+               return;
+
+       yield_depth++;
+
         /* time() seems to be a pretty expensive syscall, so avoid calling it too much.
          * Once per loop iteration is pleanty.
          */
@@ -616,24 +612,49 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
         if (((TIME % 5) == 0) && (!expire_run))
         {
                 expire_lines();
-                FOREACH_MOD(I_OnBackgroundTimer,OnBackgroundTimer(TIME));
+               if (process_module_sockets)
+               {
+                       /* Fix by brain - the addition of DoOneIteration means that this
+                        * can end up getting called recursively in the following pattern:
+                        *
+                        * m_spanningtree DoPingChecks
+                        * (server pings out and is squit)
+                        * (squit causes call to DoOneIteration)
+                        * DoOneIteration enters here
+                        * calls DoBackground timer
+                        * enters m_spanningtree DoPingChecks... see step 1.
+                        *
+                        * This should do the job and fix the bug.
+                        */
+                       FOREACH_MOD(I_OnBackgroundTimer,OnBackgroundTimer(TIME));
+               }
                 TickMissedTimers(TIME);
                 expire_run = true;
+               yield_depth--;
                 return;
         }   
         else if ((TIME % 5) == 1)
         {
                 expire_run = false;
         }
+
+       if (iterations++ == 15)
+       {
+               iterations = 0;
+               DoBackgroundUserStuff(TIME);
+       }
  
         /* Once a second, do the background processing */
         if (TIME != OLDTIME)
         {
                 if (TIME < OLDTIME)
                         WriteOpers("*** \002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %d secs.",abs(OLDTIME-TIME));
-                DoBackgroundUserStuff(TIME);
+               if ((TIME % 3600) == 0)
+               {
+                       MaintainWhoWas(TIME);
+               }
         }
-               
+
         /* Process timeouts on module sockets each time around
          * the loop. There shouldnt be many module sockets, at
          * most, 20 or so, so this won't be much of a performance
@@ -650,7 +671,10 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
          * servers... so its nice and easy, just one call.
          */
         if (!(numberactive = SE->Wait(activefds)))
+       {
+               yield_depth--;
                 return;
+       }
 
         /**
          * Now process each of the fd's. For users, we have a fast
@@ -659,6 +683,8 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
          * listening ports or module sockets though, things could get
          * ugly.
          */
+       log(DEBUG,"There are %d fd's to process.",numberactive);
+
         for (unsigned int activefd = 0; activefd < numberactive; activefd++)
         {
                 int socket_type = SE->GetType(activefds[activefd]);
@@ -666,6 +692,7 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
                 {
                         case X_ESTAB_CLIENT:
 
+                               log(DEBUG,"Type: X_ESTAB_CLIENT: fd=%d",activefds[activefd]);
                                 cu = fd_ref_table[activefds[activefd]];
                                 if (cu)
                                         ProcessUser(cu);  
@@ -674,8 +701,10 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
         
                         case X_ESTAB_MODULE:
 
+                               log(DEBUG,"Type: X_ESTAB_MODULE: fd=%d",activefds[activefd]);
+
                                if (!process_module_sockets)
-                                       return;
+                                       break;
 
                                 /* Process module-owned sockets.
                                  * Modules are encouraged to inherit their sockets from
@@ -685,8 +714,9 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
               
                                 if ((s) && (!s->Poll()))
                                 {
-                                        log(DEBUG,"Socket poll returned false, close and bail");
+                                        log(DEBUG,"inspircd.cpp: Socket poll returned false, close and bail");
                                         SE->DelFd(s->GetFd());
+                                       socket_ref[activefds[activefd]] = NULL;
                                         for (std::vector<InspSocket*>::iterator a = module_sockets.begin(); a < module_sockets.end(); a++)
                                         {
                                                 s_del = (InspSocket*)*a;
@@ -699,6 +729,11 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
                                         s->Close();
                                         delete s;
                                 }
+                               else if (!s)
+                               {
+                                       log(DEBUG,"WTF, X_ESTAB_MODULE for nonexistent InspSocket, removed!");
+                                       SE->DelFd(s->GetFd());
+                               }
                         break;
 
                         case X_ESTAB_DNS:
@@ -710,12 +745,15 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
                                  * and independent of the mainloop.
                                  */
 #ifndef THREADED_DNS
+                               log(DEBUG,"Type: X_ESTAB_DNS: fd=%d",activefds[activefd]);
                                 dns_poll(activefds[activefd]);
 #endif
                         break;
 
                        case X_LISTEN:
 
+                               log(DEBUG,"Type: X_LISTEN_MODULE: fd=%d",activefds[activefd]);
+
                                 /* It's a listener */
                                 uslen = sizeof(sock_us);
                                 length = sizeof(client);
@@ -738,7 +776,7 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
                                                 }
                                                 catch (ModuleException& modexcept)
                                                 {
-                                                        log(DEBUG,"Module exception cought: %s",modexcept.GetReason()); \
+                                                        log(DEBUG,"Module exception cought: %s",modexcept.GetReason());
                                                 }
                                         }
                                         stats->statsAccept++;
@@ -760,9 +798,12 @@ void InspIRCd::DoOneIteration(bool process_module_sockets)
                                  * what we would do, so for now, its going
                                  * to safely do bugger all.
                                  */
+                               log(DEBUG,"Type: X_WHAT_THE_FUCK_BBQ: fd=%d",activefds[activefd]);
+                               SE->DelFd(activefds[activefd]);
                         break;
                 }
         }
+       yield_depth--;
 }
 
 int InspIRCd::Run()
@@ -771,12 +812,16 @@ int InspIRCd::Run()
        
         LoadAllModules(this);
 
+       /* Just in case no modules were loaded - fix for bug #101 */
+       this->BuildISupport();
+
         printf("\nInspIRCd is now running!\n");
        
        if (!Config->nofork)
        {
-               freopen("/dev/null","w",stdout);
-               freopen("/dev/null","w",stderr);
+               fclose(stdout);
+               fclose(stderr);
+               fclose(stdin);
        }
 
        /* Add the listening sockets used for client inbound connections
@@ -789,6 +834,8 @@ int InspIRCd::Run()
 
        /* main loop, this never returns */
        expire_run = false;
+       yield_depth = 0;
+       iterations = 0;
 
        while (true)
        {
@@ -806,9 +853,18 @@ int InspIRCd::Run()
 
 int main(int argc, char** argv)
 {
-        ServerInstance = new InspIRCd(argc, argv);
-        ServerInstance->Run();
-        delete ServerInstance;
-        return 0;
+       try
+       {
+               ServerInstance = new InspIRCd(argc, argv);
+               ServerInstance->Run();
+               delete ServerInstance;
+       }
+       catch (std::bad_alloc)
+       {
+               log(DEFAULT,"You are out of memory! (got exception std::bad_alloc!)");
+               send_error("**** OUT OF MEMORY **** We're gonna need a bigger boat!");
+               printf("Out of memory! (got exception std::bad_alloc!");
+       }
+       return 0;
 }