Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 20th, 2012  |  syntax: None  |  size: 5.04 KB  |  hits: 11  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Based on the log message, we have been through this line:
  2.  
  3. https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/listen.cpp#L292
  4.  
  5. Context :
  6.  
  7.                 SockAddr from;
  8.                 int s = accept(*it, from.raw(), &from.addressSize);
  9.                 if ( s < 0 ) {
  10.                     int x = errno; // so no global issues
  11.                     if ( x == ECONNABORTED || x == EBADF ) {
  12.                         log() << "Listener on port " << _port << " aborted" << endl;
  13.                         return;
  14.                     }
  15.  
  16. Okay, ``return`` ... that doesn't sound so bad.  Right?
  17. Wrong!
  18.  
  19. That's the impl of ``initAndListen()`` for the class ``Listener`` :
  20. https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/listen.h#L44
  21.  
  22. ```
  23.         void initAndListen(); // never returns unless error (start a thread)
  24. ```
  25.  
  26. Okay, so the thread exits?  That's not so bad, right?  
  27. Wrong!  And also, wrong!
  28.  
  29. How'd we get here ...
  30.  
  31. Like any good C program, we start with main() -- in this case, from
  32.  
  33. https://github.com/mongodb/mongo/blob/master/src/mongo/db/db.cpp#L1103
  34.  
  35. here's the end of main() :
  36.  
  37. ```
  38. int main(int argc, char* argv[]) {
  39.     ...
  40.     StartupTest::runTests();
  41.     initAndListen(cmdLine.port);
  42.     dbexit(EXIT_CLEAN);
  43.     return 0;
  44. }
  45. ```
  46.  
  47. ``initAndListen()`` call goes up to [line 542](https://github.com/mongodb/mongo/blob/master/src/mongo/db/db.cpp#L542)
  48.  
  49. ```
  50.     void initAndListen(int listenPort) {
  51.         try {
  52.             _initAndListen(listenPort);
  53.         }
  54.         catch ( DBException &e ) {
  55.             log() << "exception in initAndListen: " << e.toString() << ", terminating" << endl;
  56.             dbexit( EXIT_UNCAUGHT );
  57.         }
  58.         catch ( std::exception &e ) {
  59.             log() << "exception in initAndListen std::exception: " << e.what() << ", terminating" << endl;
  60.             dbexit( EXIT_UNCAUGHT );
  61.         }
  62.         catch ( int& n ) {
  63.             log() << "exception in initAndListen int: " << n << ", terminating" << endl;
  64.             dbexit( EXIT_UNCAUGHT );
  65.         }
  66.         catch(...) {
  67.             log() << "exception in initAndListen, terminating" << endl;
  68.             dbexit( EXIT_UNCAUGHT );
  69.         }
  70.     }
  71. ```
  72.  
  73. delegates to [line 436](https://github.com/mongodb/mongo/blob/master/src/mongo/db/db.cpp#L436):
  74.  
  75. ```
  76.     void _initAndListen(int listenPort ) {
  77.  
  78.         Client::initThread("initandlisten");
  79.  
  80.         Database::_openAllFiles = false;
  81.  
  82.         Logstream::get().addGlobalTee( new RamLog("global") );
  83.  
  84.         ...
  85.  
  86.         Module::initAll();
  87.  
  88.         if ( scriptingEnabled ) {
  89.             ScriptEngine::setup();
  90.             globalScriptEngine->setCheckInterruptCallback( jsInterruptCallback );
  91.             globalScriptEngine->setGetInterruptSpecCallback( jsGetInterruptSpecCallback );
  92.         }
  93.  
  94.         repairDatabasesAndCheckVersion();
  95.  
  96.         ...
  97.  
  98.         if( !noauth ) {
  99.             // open admin db in case we need to use it later. TODO this is not the right way to
  100.             // resolve this.
  101.             writelock lk;
  102.             Client::Context c("admin",dbpath,false);
  103.         }
  104.  
  105.         listen(listenPort);
  106.  
  107.         // listen() will return when exit code closes its socket.
  108.         exitCleanly(EXIT_NET_ERROR);
  109.     }
  110. ```
  111.  
  112. at which point the ``listen()`` call brings us up to [line 226](https://github.com/mongodb/mongo/blob/master/src/mongo/db/db.cpp#L226) :
  113.  
  114. ```
  115.     void listen(int port) {
  116.         //testTheDb();
  117.         MessageServer::Options options;
  118.         options.port = port;
  119.         options.ipList = cmdLine.bind_ip;
  120.  
  121.         MessageServer * server = createServer( options , new MyMessageHandler() );
  122.         server->setAsTimeTracker();
  123.  
  124.         startReplication();
  125.         if ( !noHttpInterface )
  126.             boost::thread web( boost::bind(&webServerThread, new RestAdminAccess() /* takes ownership */));
  127.  
  128. #if(TESTEXHAUST)
  129.         boost::thread thr(testExhaust);
  130. #endif
  131.         server->run();
  132.     }
  133. ```
  134.  
  135. What's that ``server`` being ``run()``?  It's a ``MessageServer``, says [message_server.h](https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/message_server.h) :
  136.  
  137. ```
  138.     MessageServer * createServer( const MessageServer::Options& opts , MessageHandler * handler );
  139. ```
  140.  
  141. Implementation :
  142.  
  143. https://github.com/mongodb/mongo/blob/master/src/mongo/util/net/message_server_port.cpp#L113
  144.  
  145. ```
  146. #include "listen.h"
  147.  
  148. ...
  149.  
  150.     class PortMessageServer : public MessageServer , public Listener {
  151. ...
  152.         void run() {
  153.             initAndListen();
  154.         }
  155.  
  156.         virtual bool useUnixSockets() const { return true; }
  157.     };
  158.  
  159.  
  160.     MessageServer * createServer( const MessageServer::Options& opts , MessageHandler * handler ) {
  161.         return new PortMessageServer( opts , handler );
  162.     }
  163.  
  164. ```
  165.  
  166. Which is where we came in.  Our journey is complete.
  167.  
  168. To sum up :  
  169.  
  170. * Get ``ECONNABORTED`` or ``EBADF`` from socket ``accept()`` ==>
  171. * Return from ``initAndListen()`` ==>
  172. * Return from ``PortMessageServer::run()`` ==>
  173. * Return from ``listen()`` in db.cpp ==>
  174. * Return from ``_initAndListen()`` in db.cpp ==>
  175. * Return from ``initAndListen()`` in db.cpp ==>
  176. * Call ``dbexit(EXIT_CLEAN);`` and then return from ``main()`` ==>
  177. * Game over, dude!