Ticket #34: lotsa_sockets_updated.diff

File lotsa_sockets_updated.diff, 27.0 kB (added by rogerdpack, 5 months ago)

updated diff. It includes a few extra functionality not related to this one [GetMaxTimers?] which should probably be extracted, and applies to a different ticket

  • em.cpp

    old new  
    6464        MaxOutstandingTimers = count; 
    6565} 
    6666 
     67 /************************ 
     68 * 
     69  If we're on linux, and using select, and sd >= FD_SETSIZE then reject it-- we can't fit it into a select!  The problem being that with linux, the first parameter to select must be < FD_SETSIZE (it checks up to that many file descriptors). 
     70        i.e., if you get a file descriptor with a value as high as FD_SETSIZE, you cannot put that descriptor into an fd_set. (from http://www.delorie.com/gnu/docs/glibc/libc_248.html) 
     71        With windows, it appears that the total number of sockets it will cram into an fd_set is FD_SETSIZE, so...it basically ignores the call to FD_SET if the fd_set is already too populated, resulting in <cough> us losing a lot of data.  So it's the same logic check, but it errs in different parameters. 
     72        http://doc.ddart.net/msdn/header/include/winsock.h.html -- we use winsock.h, not winsock2.h 
     73         
     74        todo add this to udp, well just about everything (?) Note that it's dangerous to 'close' it since it still will make it to select 
     75  
     76        So note that on linux descriptor numbers must be less than FD_SETSIZE, and on windows, the sum of descriptor counts must be < FD_SETSIZE. 
     77 ***********************/ 
     78  
     79 bool EventMachine_t::CantAffordNewSocket(int socket_number) 
     80 { 
     81  
     82  
     83 #ifndef OS_WIN32 
     84   if(bEpoll or bKqueue) 
     85        return 0; // can afford 
     86   if(socket_number >= (FD_SETSIZE -1)) // no idea why the -1 is necessary, but it seems to be on os x at least (errs without it) 
     87        return 1; 
     88   else 
     89        return 0; 
     90 #else 
     91   // we leave one for  the loop break reader, etc. (seems to work). 
     92   if((Descriptors.size() + NewDescriptors.size()) < (FD_SETSIZE - 3)) 
     93        return 0; // can afford (not not afford) 
     94   else 
     95        return 1; // can't afford 
     96 #endif 
     97  
     98 } 
     99  
     100 void EventMachine_t::AssertValidDescriptorsLength() 
     101 { 
     102        if(bEpoll or bKqueue) 
     103                return; // always return true in this case--we don't run out. 
     104        int socket_count = Descriptors.size() + NewDescriptors.size();  
     105        int max_allowed = FD_SETSIZE - 2; // since we need FD_SETSIZE -1 'slot' to hold the loop breaker 
     106        assert(socket_count <= max_allowed);; // should hold true for linux, too, by a freak of logic luck (if descriptors.size > FD_SETSIZE -2 then for sure we have one in there whose descriptor number >= FD_SETSIZE - 1 (?) 
     107  
     108 } 
    67109 
    68110 
    69111/****************************** 
     
    153195        /* Temporary. 
    154196         * See comments under _UseEpoll. 
    155197         */ 
    156  
     198         
    157199        #ifdef HAVE_KQUEUE 
    158200        bKqueue = true; 
     201        #else 
    159202        #endif 
    160203} 
    161204 
     
    182225        gTerminateSignalReceived = true; 
    183226} 
    184227 
     228/***************************** 
     229EventMachine_t::GetTimerQuantumMills 
     230******************************/ 
    185231 
     232int  EventMachine_t::GetTimerQuantumMills () 
     233{ 
     234 return Quantum.tv_sec * 1000 + Quantum.tv_usec / 1000; 
     235} 
    186236 
     237 
    187238/******************************* 
    188239EventMachine_t::SetTimerQuantum 
    189240*******************************/ 
     
    463514                //  descriptor is closed anyway. This is different from the case where 
    464515                //  the socket has already been closed but the descriptor in the ED object 
    465516                //  hasn't yet been set to INVALID_SOCKET. 
    466               int i, j; 
    467               int nSockets = Descriptors.size(); 
    468               for (i=0, j=0; i < nSockets; i++) { 
    469                       EventableDescriptor *ed = Descriptors[i]; 
    470                       assert (ed); 
    471                       if (ed->ShouldDelete()) { 
     517              int i, j; 
     518              int nSockets = Descriptors.size(); 
     519              for (i=0, j=0; i < nSockets; i++) { 
     520                      EventableDescriptor *ed = Descriptors[i]; 
     521                      assert (ed); 
     522                      if (ed->ShouldDelete()) { 
    472523                                if (ed->GetSocket() != INVALID_SOCKET) { 
    473524                                        assert (bEpoll); // wouldn't be in this method otherwise. 
    474525                                        assert (epfd != -1); 
     
    479530                                                snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno)); 
    480531                                                throw std::runtime_error (buf); 
    481532                                        } 
    482                               } 
     533                              } 
    483534 
    484535                                ModifiedDescriptors.erase (ed); 
    485536                                delete ed; 
     
    658709        #endif 
    659710} 
    660711 
     712/****************************** 
     713EventMachine_t::_SelectOnceErrorController 
     714******************************/ 
    661715 
     716int EventMachine_t::_SelectOnceErrorControlled() // for win32 only -- this does help, in some instances.  There seems to be some lurking other problems, too, though--like why don't connections close right, and then sometimes select still fails--and in a bad way. 
     717{ 
     718/* Some windows notes (this function used mostly for windows--I hope) 
     719todo run on linux EINVAL, too 
     720 note that windows sometimes, for some reason if you have open sockets, then you do File.open (?) then one of your open sockets no longer responds to select.  Maybe File.open 's file descriptor is ploughing a socket descriptor? 
     721 note also that on windows, server editions you can have more than 256 (msvcrt.dll) or 2048 (msvcrtXX.dll) file descriptors total, per process, so our setting FD_SETSIZE to 2048 might could use to be raised in those cases.  But I'd say leaving it at 2048 is good till it becomes a problem for someone. 
     722update--appears that it doesn't matter what you set FD_SETSIZE to be, it only 'works' up to 64, for some reason.  Maybe ruby itself 'redefines' FD_SETSIZE to be low? So we need to set it? todo (there's a test that tests this, you can set FD_SETSIZE to whatever, run the test--it errs if you set it above 64! 
     723 it appears that even having this loop doesn't solve all the problems, as select sometimes returns '3' even when none of them even requested to read or write--probably corruption 
     724*/ 
    662725 
     726        SelectData_t SelectData; 
     727        fd_set test_one_read, test_one_write, test_one_err; // do we need the err one, though? 
     728        FD_ZERO(&(SelectData.fdreads)); 
     729        FD_ZERO(&(SelectData.fdwrites)); 
     730        FD_ZERO(&test_one_read); 
     731        timeval tv_lpbr = {0,0}; 
     732        int select_return = EmSelect(LoopBreakerReader, &test_one_read, NULL, NULL, &tv_lpbr); 
     733        if(select_return < 0) 
     734                printf("arr bad loopbreaker! please report to EM\n\n\n"); 
     735        FD_SET (LoopBreakerReader, &(SelectData.fdreads)); 
     736                SelectData.maxsocket = LoopBreakerReader; 
     737 
     738        // prepare the sockets for reading and writing, with error checking this time 
     739        size_t i; 
     740        int failed_count = 0; 
     741        for (i = 0; i < Descriptors.size(); i++) { 
     742                timeval tv_zero = {0, 1}; // set this to actually wait a split second so that some weird weird weird obscure select failures will show through (if you set FD_SETSIZE to 2048, slam it, then sometimes select'ing on 0 doesn't work 'well enough' --it returns 1, then when you pass the whole group to select again, it errs. 
     743                EventableDescriptor *ed = Descriptors[i]; 
     744                assert (ed); 
     745                int sd = ed->GetSocket(); 
     746                assert (sd != INVALID_SOCKET); 
     747                FD_ZERO(&test_one_read); 
     748                FD_ZERO(&test_one_write); 
     749 
     750                if (ed->SelectForRead()) 
     751                { 
     752                        int select_return = EmSelect(sd+1, &test_one_read, NULL, &test_one_err, &tv_zero); 
     753                        if(select_return >= 0) 
     754                                FD_SET (sd, &(SelectData.fdreads)); 
     755                        else 
     756                        { 
     757                                failed_count++; 
     758                        } 
     759                } 
     760                if (ed->SelectForWrite()) 
     761                { 
     762                        FD_SET(sd, &test_one_write); 
     763                        int select_return = EmSelect(sd+1, &test_one_write, NULL, NULL, &tv_zero); 
     764                        if(select_return >= 0) 
     765                                FD_SET (sd, &(SelectData.fdwrites)); 
     766                        else 
     767                        { 
     768                                failed_count++; 
     769                        } 
     770                } 
     771 
     772                if (SelectData.maxsocket < sd) 
     773                        SelectData.maxsocket = sd; 
     774        } 
     775         
     776        //if(failed_count > 0) 
     777        //      printf("at least one failed! -- FD_SETSIZE == %d, our descriptors size %d\n", FD_SETSIZE, Descriptors.size()); 
     778 
     779        return SelectData._Select(); 
     780 
     781} 
    663782/****************************** 
    664783EventMachine_t::_RunSelectOnce 
    665784******************************/ 
     
    679798        //cerr << "X"; 
    680799 
    681800        /* This protection is now obsolete, because we will ALWAYS 
    682          * have at least one descriptor (the loop-breaker) to read. 
     801         * have at least one descriptor (the loop-breaker) to read.  
    683802         */ 
    684803        /* 
    685804        if (Descriptors.size() == 0) { 
     
    689808                return true; 
    690809                #endif 
    691810                #ifdef OS_WIN32 
    692                 Sleep (200); 
     811                Sleep (200);  
    693812                return true; 
    694813                #endif 
    695814        } 
     
    703822 
    704823        int maxsocket = 0; 
    705824        */ 
     825        AssertValidDescriptorsLength(); 
    706826 
    707827        // Always read the loop-breaker reader. 
    708828        // Changed 23Aug06, provisionally implemented for Windows with a UDP socket 
    709829        // running on localhost with a randomly-chosen port. (*Puke*) 
    710830        // Windows has a version of the Unix pipe() library function, but it doesn't 
    711831        // give you back descriptors that are selectable. 
     832 
    712833        FD_SET (LoopBreakerReader, &(SelectData.fdreads)); 
    713834        if (SelectData.maxsocket < LoopBreakerReader) 
    714835                SelectData.maxsocket = LoopBreakerReader; 
    715836 
    716837        // prepare the sockets for reading and writing 
    717838        size_t i; 
    718         for (i = 0; i < Descriptors.size(); i++) { 
     839        for (i = 0; i < Descriptors.size(); i++) { // aren't we supposed to do this just once? 
    719840                EventableDescriptor *ed = Descriptors[i]; 
    720841                assert (ed); 
    721842                int sd = ed->GetSocket(); 
    722843                assert (sd != INVALID_SOCKET); 
    723844 
    724845                if (ed->SelectForRead()) 
     846                { 
    725847                        FD_SET (sd, &(SelectData.fdreads)); 
     848                } 
    726849                if (ed->SelectForWrite()) 
     850                { 
    727851                        FD_SET (sd, &(SelectData.fdwrites)); 
     852                } 
    728853 
    729854                if (SelectData.maxsocket < sd) 
    730855                        SelectData.maxsocket = sd; 
    731856        } 
    732  
    733  
     857         
    734858        { // read and write the sockets 
    735859                //timeval tv = {1, 0}; // Solaris fails if the microseconds member is >= 1000000. 
    736860                //timeval tv = Quantum; 
    737861                SelectData.tv = Quantum; 
    738862                int s = SelectData._Select(); 
     863                #ifdef OS_WIN32 
     864                if(s<0) 
     865                { 
     866                #else 
     867                if(s==EINVAL) 
     868                { 
     869                        printf("select EINVAL on linux unanticipated--please report to EM"); 
     870                #endif 
     871                        s = _SelectOnceErrorControlled(); // hack to run it again with error checking on each socket, should it fail because of one--this until we can figure out and stamp out all win32 errors.  Till then, just run select on error checked items. 
     872                } 
     873 
    739874                //rb_thread_blocking_region(xxx,(void*)&SelectData,RB_UBF_DFL,0); 
    740875                //int s = EmSelect (SelectData.maxsocket+1, &(SelectData.fdreads), &(SelectData.fdwrites), NULL, &(SelectData.tv)); 
    741876                //int s = SelectData.nSockets; 
     877 
    742878                if (s > 0) { 
    743879                        /* Changed 01Jun07. We used to handle the Loop-breaker right here. 
    744880                         * Now we do it AFTER all the regular descriptors. There's an 
     
    757893                                assert (sd != INVALID_SOCKET); 
    758894 
    759895                                if (FD_ISSET (sd, &(SelectData.fdwrites))) 
     896                                { 
    760897                                        ed->Write(); 
     898                                } 
    761899                                if (FD_ISSET (sd, &(SelectData.fdreads))) 
     900                                { 
    762901                                        ed->Read(); 
     902                                } 
    763903                        } 
    764904 
    765905                        if (FD_ISSET (LoopBreakerReader, &(SelectData.fdreads))) 
     906                        { 
    766907                                _ReadLoopBreaker(); 
     908                        } 
    767909                } 
    768910                else if (s < 0) { 
    769911                        // select can fail on error in a handful of ways. 
     
    772914                        // so keep the wait short. 
    773915                        timeval tv = {0, ((errno == EINTR) ? 5 : 50) * 1000}; 
    774916                        EmSelect (0, NULL, NULL, NULL, &tv); 
     917                        #ifdef OS_WIN32 
     918                        Sleep(100); 
     919                        #endif 
    775920                } 
    776921        } 
    777922 
     
    9741119 
    9751120        // From here on, ALL error returns must close the socket. 
    9761121        // Set the new socket nonblocking. 
     1122        if(CantAffordNewSocket(sd)) 
     1123        { 
     1124                //printf("connect ignoring too large of a socket for select bad 3.5"); 
     1125                closesocket (sd); 
     1126                return NULL; 
     1127        } 
     1128   
    9771129        if (!SetSocketNonblocking (sd)) { 
    9781130                closesocket (sd); 
    9791131                return NULL; 
     
    9831135        setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one)); 
    9841136 
    9851137        const char *out = NULL; 
    986  
    987        #ifdef OS_UNIX 
     1138         
     1139#ifdef OS_UNIX 
    9881140        //if (connect (sd, (sockaddr*)&pin, sizeof pin) == 0) { 
    9891141        if (connect (sd, bind_as, bind_size) == 0) { 
    9901142                // This is a connect success, which Linux appears 
     
    10811233        } 
    10821234        else { 
    10831235                // The error from connect was something other then WSAEWOULDBLOCK. 
     1236                throw std::runtime_error ("unimplemented2"); 
    10841237        } 
    10851238 
    10861239        #endif 
    10871240 
     1241        AssertValidDescriptorsLength(); 
    10881242        if (out == NULL) 
    10891243                closesocket (sd); 
    10901244        return out; 
     
    12551409        if (sd_accept == INVALID_SOCKET) { 
    12561410                goto fail; 
    12571411        } 
     1412        // TODO ask about accepts, tho--should we just clear them or what?  I assume so.         
     1413        if(CantAffordNewSocket(sd_accept)) 
     1414        { 
     1415                goto fail; 
     1416        } 
    12581417 
    12591418        /* 
    12601419        memset (&sin, 0, sizeof(sin)); 
     
    13221481                output_binding = ad->GetBinding().c_str(); 
    13231482        } 
    13241483 
     1484        AssertValidDescriptorsLength(); 
    13251485        return output_binding; 
    1326  
    13271486        fail: 
    13281487        if (sd_accept != INVALID_SOCKET) 
    13291488                closesocket (sd_accept); 
     
    17781937 
    17791938 
    17801939//#endif // OS_UNIX 
    1781  
  • em.h

    old new  
    8282                void ArmKqueueWriter (EventableDescriptor*); 
    8383                void ArmKqueueReader (EventableDescriptor*); 
    8484 
     85                int GetTimerQuantumMills (); 
     86                void AssertValidDescriptorsLength(); 
     87                bool CantAffordNewSocket(int descriptor_number); 
    8588                void SetTimerQuantum (int); 
    8689                static void SetuidString (const char*); 
    8790                static int SetRlimitNofile (int); 
     
    100103                void _ModifyDescriptors(); 
    101104                void _InitializeLoopBreaker(); 
    102105 
     106                int _SelectOnceErrorControlled(); 
    103107                bool _RunSelectOnce(); 
    104108                bool _RunEpollOnce(); 
    105109                bool _RunKqueueOnce(); 
  • eventmachine.h

    old new  
    4646        const char *evma_open_keyboard(); 
    4747        void evma_set_tls_parms (const char *binding, const char *privatekey_filename, const char *certchain_filenane); 
    4848        void evma_start_tls (const char *binding); 
     49        int evma_get_sockname (const char *binding, struct sockaddr*); 
    4950        int evma_get_peername (const char *binding, struct sockaddr*); 
    5051        int evma_get_sockname (const char *binding, struct sockaddr*); 
    5152        int evma_get_subprocess_pid (const char *binding, pid_t*); 
     
    5455        int evma_send_datagram (const char *binding, const char *data, int data_length, const char *address, int port); 
    5556        int evma_get_comm_inactivity_timeout (const char *binding, /*out*/int *value); 
    5657        int evma_set_comm_inactivity_timeout (const char *binding, /*in,out*/int *value); 
     58        int evma_get_timer_quantum_value (); /* passes it straight out */ 
    5759        int evma_get_outbound_data_size (const char *binding); 
    5860        int evma_send_file_data_to_connection (const char *binding, const char *filename); 
    5961 
  • rubymain.cpp

    old new  
    206206        return Qnil; 
    207207} 
    208208 
     209 
    209210/******************** 
    210211t_get_subprocess_pid 
    211212********************/ 
     
    304305 
    305306        const char *f = evma_connect_to_server (StringValuePtr(server), NUM2INT(port)); 
    306307        if (!f || !*f) 
    307                 rb_raise (rb_eRuntimeError, "no connection"); 
     308                rb_raise (rb_eRuntimeError, "no connection t_connect_server meaning that the attempt to connect to the server failed somehow f_pointer == (%d)", f); 
    308309        return rb_str_new2 (f); 
    309310} 
    310311 
     
    375376} 
    376377 
    377378 
     379/***************** 
     380t_get_timer_quantum_mills 
     381Returns current timer quantum value 
     382******************/ 
     383static VALUE 
     384t_get_timer_quantum_mills (VALUE self) 
     385{ 
     386  return INT2NUM(evma_get_timer_quantum_value()); 
     387} 
    378388 
     389 
    379390/******************* 
    380391t_set_timer_quantum 
    381392*******************/ 
     
    596607        rb_define_module_function (EmModule, "stop", (VALUE(*)(...))t_stop, 0); 
    597608        rb_define_module_function (EmModule, "signal_loopbreak", (VALUE(*)(...))t_signal_loopbreak, 0); 
    598609        rb_define_module_function (EmModule, "library_type", (VALUE(*)(...))t_library_type, 0); 
     610        rb_define_module_function (EmModule, "get_timer_quantum_mills", (VALUE(*)(...))t_get_timer_quantum_mills, 0); 
    599611        rb_define_module_function (EmModule, "set_timer_quantum", (VALUE(*)(...))t_set_timer_quantum, 1); 
    600612        rb_define_module_function (EmModule, "set_max_timer_count", (VALUE(*)(...))t_set_max_timer_count, 1); 
    601613        rb_define_module_function (EmModule, "setuid_string", (VALUE(*)(...))t_setuid_string, 1); 
  • extconf.rb

    old new  
    3131      have_library('gdi32') 
    3232    exit 
    3333  end 
     34    
    3435 
    3536  flags << "-D OS_WIN32" 
    3637  flags << '-D BUILD_FOR_RUBY' 
     
    199200  $CFLAGS += ' ' + flags.join(' ') 
    200201end 
    201202 
     203create_makefile "rubyeventmachine" 
     204# now some hacks for it. ugh. 
    202205 
    203 create_makefile "rubyeventmachine" 
     206def replace_within_makefile this_string, with_this_string 
     207  makefile = File.read("Makefile") 
     208  makefile.gsub!(this_string, with_this_string) 
     209  File.open("Makefile", "wb").write(makefile) 
     210end 
     211 
     212if RUBY_PLATFORM =~ /mingw/ 
     213  print "noticed mingw, accomodating" 
     214  replace_within_file "DLDFLAGS =", "DLDFLAGS = -lstdc++ " # it misses these libs for some reason. silly makefile maker 
     215end 
     216 
     217uname = `uname -a` 
     218if uname =~ /RELEASE_PPC/ # this known to work with Leopard, at least 
     219    print "noticed ppc, accomodating" 
     220    replace_within_makefile "i386", "ppc" # yep 
     221end  
  • cmain.cpp

    old new  
    3535        // we're just being linked into. 
    3636        //InstallSignalHandlers(); 
    3737        if (EventMachine) 
    38                 throw std::runtime_error ("already initialized"); 
     38                throw std::runtime_error ("evma_initialize_library already initialized"); 
    3939        EventMachine = new EventMachine_t (cb); 
    4040        if (bUseEpoll) 
    4141                EventMachine->_UseEpoll(); 
     
    5151extern "C" void evma_release_library() 
    5252{ 
    5353        if (!EventMachine) 
    54                 throw std::runtime_error ("not initialized"); 
     54                throw std::runtime_error ("evma_release_library not initialized"); 
    5555        delete EventMachine; 
    5656        EventMachine = NULL; 
    5757} 
     
    6464extern "C" void evma_run_machine() 
    6565{ 
    6666        if (!EventMachine) 
    67                 throw std::runtime_error ("not initialized"); 
     67                throw std::runtime_error ("evma_run_machine not initialized"); 
    6868        EventMachine->Run(); 
    6969} 
    7070 
     
    7676extern "C" const char *evma_install_oneshot_timer (int seconds) 
    7777{ 
    7878        if (!EventMachine) 
    79                 throw std::runtime_error ("not initialized"); 
     79                throw std::runtime_error ("evma_install_oneshot_timer not initialized"); 
    8080        return EventMachine->InstallOneshotTimer (seconds); 
    8181} 
    8282 
     
    8888extern "C" const char *evma_connect_to_server (const char *server, int port) 
    8989{ 
    9090        if (!EventMachine) 
    91                 throw std::runtime_error ("not initialized"); 
     91                throw std::runtime_error ("evma_connect_to_server not initialized"); 
    9292        return EventMachine->ConnectToServer (server, port); 
    9393} 
    9494 
     
    9999extern "C" const char *evma_connect_to_unix_server (const char *server) 
    100100{ 
    101101        if (!EventMachine) 
    102                 throw std::runtime_error ("not initialized"); 
     102                throw std::runtime_error ("evma_connect_to_unix_server not initialized"); 
    103103        return EventMachine->ConnectToUnixServer (server); 
    104104} 
    105105 
     
    111111extern "C" const char *evma_create_tcp_server (const char *address, int port) 
    112112{ 
    113113        if (!EventMachine) 
    114                 throw std::runtime_error ("not initialized"); 
     114                throw std::runtime_error ("evma_create_tcp_server not initialized"); 
    115115        return EventMachine->CreateTcpServer (address, port); 
    116116} 
    117117 
     
    122122extern "C" const char *evma_create_unix_domain_server (const char *filename) 
    123123{ 
    124124        if (!EventMachine) 
    125                 throw std::runtime_error ("not initialized"); 
     125
     126                throw std::runtime_error ("evma_create_unix_domain_server not initialized"); 
     127
    126128        return EventMachine->CreateUnixDomainServer (filename); 
    127129} 
    128130 
     
    133135extern "C" const char *evma_open_datagram_socket (const char *address, int port) 
    134136{ 
    135137        if (!EventMachine) 
    136                 throw std::runtime_error ("not initialized"); 
     138                throw std::runtime_error ("evma_open_datagram_socket not initialized"); 
    137139        return EventMachine->OpenDatagramSocket (address, port); 
    138140} 
    139141 
     
    144146extern "C" const char *evma_open_keyboard() 
    145147{ 
    146148        if (!EventMachine) 
    147                 throw std::runtime_error ("not initialized"); 
     149                throw std::runtime_error ("evma_open_keyboard not initialized"); 
    148150        return EventMachine->OpenKeyboard(); 
    149151} 
    150152 
     
    157159extern "C" int evma_send_data_to_connection (const char *binding, const char *data, int data_length) 
    158160{ 
    159161        if (!EventMachine) 
    160                 throw std::runtime_error ("not initialized"); 
     162                throw std::runtime_error ("evma_send_data_to_connection not initialized"); 
    161163        return ConnectionDescriptor::SendDataToConnection (binding, data, data_length); 
    162164} 
    163165 
     
    168170extern "C" int evma_send_datagram (const char *binding, const char *data, int data_length, const char *address, int port) 
    169171{ 
    170172  if (!EventMachine) 
    171                 throw std::runtime_error ("not initialized"); 
     173                throw std::runtime_error ("evma_send_datagram not initialized"); 
    172174        return DatagramDescriptor::SendDatagram (binding, data, data_length, address, port); 
    173175} 
    174176 
     
    180182extern "C" void evma_close_connection (const char *binding, int after_writing) 
    181183{ 
    182184        if (!EventMachine) 
    183                 throw std::runtime_error ("not initialized"); 
     185                throw std::runtime_error ("evma_close_connection not initialized"); 
    184186        ConnectionDescriptor::CloseConnection (binding, (after_writing ? true : false)); 
    185187} 
    186188 
     
    191193extern "C" int evma_report_connection_error_status (const char *binding) 
    192194{ 
    193195        if (!EventMachine) 
    194                 throw std::runtime_error ("not initialized"); 
     196                throw std::runtime_error ("evma_report_connection_error_status not initialized"); 
    195197        return ConnectionDescriptor::ReportErrorStatus (binding); 
    196198} 
    197199 
     
    202204extern "C" void evma_stop_tcp_server (const char *binding) 
    203205{ 
    204206        if (!EventMachine) 
    205                 throw std::runtime_error ("not initialized"); 
     207                throw std::runtime_error ("evma_stop_tcp_server not initialized"); 
    206208        AcceptorDescriptor::StopAcceptor (binding); 
    207209} 
    208210 
     
    214216extern "C" void evma_stop_machine() 
    215217{ 
    216218        if (!EventMachine) 
    217                 throw std::runtime_error ("not initialized"); 
     219                throw std::runtime_error ("evma_stop_machine not initialized"); 
    218220        EventMachine->ScheduleHalt(); 
    219221} 
    220222 
     
    226228extern "C" void evma_start_tls (const char *binding) 
    227229{ 
    228230        if (!EventMachine) 
    229                 throw std::runtime_error ("not initialized"); 
     231                throw std::runtime_error ("evma_start_tls not initialized"); 
    230232        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
    231233        if (ed) 
    232234                ed->StartTls(); 
     
    239241extern "C" void evma_set_tls_parms (const char *binding, const char *privatekey_filename, const char *certchain_filename) 
    240242{ 
    241243        if (!EventMachine) 
    242                 throw std::runtime_error ("not initialized"); 
     244                throw std::runtime_error ("evma_set_tls_parms not initialized"); 
    243245        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
    244246        if (ed) 
    245247                ed->SetTlsParms (privatekey_filename, certchain_filename); 
     
    253255extern "C" int evma_get_peername (const char *binding, struct sockaddr *sa) 
    254256{ 
    255257        if (!EventMachine) 
    256                 throw std::runtime_error ("not initialized"); 
     258                throw std::runtime_error ("evma_get_peername not initialized"); 
    257259        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
    258260        if (ed) { 
    259261                return ed->GetPeername (sa) ? 1 : 0; 
     
    285287extern "C" int evma_get_subprocess_pid (const char *binding, pid_t *pid) 
    286288{ 
    287289        if (!EventMachine) 
    288                 throw std::runtime_error ("not initialized"); 
     290                throw std::runtime_error ("evma_get_subprocess_pid not initialized"); 
    289291        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
    290292        if (ed) { 
    291293                return ed->GetSubprocessPid (pid) ? 1 : 0; 
     
    318320extern "C" void evma_signal_loopbreak() 
    319321{ 
    320322        if (!EventMachine) 
    321                 throw std::runtime_error ("not initialized"); 
     323                throw std::runtime_error ("evma_signal_loopbreak not initialized"); 
    322324        EventMachine->SignalLoopBreaker(); 
    323325} 
    324326 
     
    331333extern "C" const char *evma__write_file (const char *filename) 
    332334{ 
    333335        if (!EventMachine) 
    334                 throw std::runtime_error ("not initialized"); 
     336                throw std::runtime_error ("evma__write_file not initialized"); 
    335337        return EventMachine->_OpenFileForWriting (filename); 
    336338} 
    337339 
     
    343345extern "C" int evma_get_comm_inactivity_timeout (const char *binding, int *value) 
    344346{ 
    345347        if (!EventMachine) 
    346                 throw std::runtime_error ("not initialized"); 
     348                throw std::runtime_error ("evma_get_comm_inactivity_timeout not initialized"); 
    347349        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
    348350        if (ed) { 
    349351                return ed->GetCommInactivityTimeout (value); 
     
    352354                return 0; //Perhaps this should be an exception. Access to an unknown binding. 
    353355} 
    354356 
     357 
     358 
    355359/******************************** 
    356360evma_set_comm_inactivity_timeout 
    357361********************************/ 
     
    359363extern "C" int evma_set_comm_inactivity_timeout (const char *binding, int *value) 
    360364{ 
    361365        if (!EventMachine) 
    362                 throw std::runtime_error ("not initialized"); 
     366                throw std::runtime_error ("evma_set_comm_inactivity_timeout not initialized"); 
    363367        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
    364368        if (ed) { 
    365369                return ed->SetCommInactivityTimeout (value); 
     
    375379 
    376380extern "C" void evma_set_timer_quantum (int interval) 
    377381{ 
    378         if (!EventMachine) 
    379                 throw std::runtime_error ("not initialized"); 
    380382        EventMachine->SetTimerQuantum (interval); 
    381383} 
    382384 
     385 
    383386/************************ 
    384387evma_set_max_timer_count 
    385388************************/ 
     
    410413extern "C" const char *evma_popen (char * const*cmd_strings) 
    411414{ 
    412415        if (!EventMachine) 
    413                 throw std::runtime_error ("not initialized"); 
     416                throw std::runtime_error ("evma_popen not initialized"); 
    414417        return EventMachine->Socketpair (cmd_strings); 
    415418} 
    416419 
     
    422425extern "C" int evma_get_outbound_data_size (const char *binding) 
    423426{ 
    424427        if (!EventMachine) 
    425                 throw std::runtime_error ("not initialized"); 
     428                throw std::runtime_error ("evma_get_outbound_data_size not initialized"); 
    426429        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
    427430        return ed ? ed->GetOutboundDataSize() : 0; 
    428431} 
     
    484487        int r; 
    485488 
    486489        if (!EventMachine) 
    487                 throw std::runtime_error("not initialized"); 
     490                throw std::runtime_error("evma_send_file_data_to_connection not initialized"); 
    488491 
    489492        int Fd = open (filename, O_RDONLY); 
    490493 
  • ed.cpp

    old new  
    604604        // so assert that as a sanity check. 
    605605        // Don't bother to make sure nbytes is less than output_buffer because 
    606606        // if it were we probably would have crashed already. 
    607         assert (nbytes > 0); 
     607        // this really can crash todo look into it:  
     608        //if(nbytes <= 0) 
     609        //      printf("arr nbytes == %d", nbytes); 
     610        //assert (nbytes > 0); 
    608611 
    609612        assert (GetSocket() != INVALID_SOCKET); 
    610613        int bytes_written = send (GetSocket(), output_buffer, nbytes, 0); 
     
    875878{ 
    876879        // TODO: This is something of a hack, or at least it's a static method of the wrong class. 
    877880        AcceptorDescriptor *ad = dynamic_cast <AcceptorDescriptor*> (Bindable_t::GetObject (binding)); 
     881        
    878882        if (ad) 
    879883                ad->ScheduleClose (false); 
    880884        else 
     
    926930                        continue; 
    927931                } 
    928932 
    929  
     933        if(MyEventMachine->CantAffordNewSocket(sd)) 
     934        { 
     935                        printf("ignoring too large of a socket for accept! aaah!"); 
     936                        shutdown (sd, 1); 
     937                        closesocket (sd); 
     938                        continue; 
     939        } 
     940         
    930941                // Disable slow-start (Nagle algorithm). Eventually make this configurable. 
    931942                int one = 1; 
    932943                setsockopt (sd, IPPROTO_TCP, TCP_NODELAY, (char*) &one, sizeof(one)); 
     
    950961                MyEventMachine->ArmKqueueReader (cd); 
    951962                #endif 
    952963        } 
     964        MyEventMachine->AssertValidDescriptorsLength(); 
    953965 
    954966} 
    955967 
  • ed.h

    old new  
    6161 
    6262                void SetEventCallback (void (*cb)(const char*, int, const char*, int)); 
    6363 
     64                virtual bool GetSockname (struct sockaddr*) {return false;} 
    6465                virtual bool GetPeername (struct sockaddr*) {return false;} 
    65                 virtual bool GetSockname (struct sockaddr*) {return false;} 
    6666                virtual bool GetSubprocessPid (pid_t*) {return false;} 
    6767 
    6868                virtual void StartTls() {}