diff options
-rw-r--r-- | src/mongo/client/scoped_db_conn_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/client.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/client.h | 21 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 4 | ||||
-rw-r--r-- | src/mongo/s/server.cpp | 4 | ||||
-rw-r--r-- | src/mongo/util/net/message_server.h | 12 | ||||
-rw-r--r-- | src/mongo/util/net/message_server_port.cpp | 6 |
7 files changed, 45 insertions, 14 deletions
diff --git a/src/mongo/client/scoped_db_conn_test.cpp b/src/mongo/client/scoped_db_conn_test.cpp index a3494225648..b4b02da84eb 100644 --- a/src/mongo/client/scoped_db_conn_test.cpp +++ b/src/mongo/client/scoped_db_conn_test.cpp @@ -126,6 +126,8 @@ public: port->reply(m, response); } + virtual void close() {} + } dummyHandler; // TODO: Take this out and make it as a reusable class in a header file. The only diff --git a/src/mongo/db/client.cpp b/src/mongo/db/client.cpp index f9a709f0189..e72553d1fbe 100644 --- a/src/mongo/db/client.cpp +++ b/src/mongo/db/client.cpp @@ -69,10 +69,6 @@ void Client::initThread(const char* desc, AbstractMessagingPort* mp) { initThread(desc, getGlobalServiceContext(), mp); } -/** - * This must be called whenever a new thread is started, so that active threads can be tracked - * so each thread has a Client object in TLS. - */ void Client::initThread(const char* desc, ServiceContext* service, AbstractMessagingPort* mp) { invariant(currentClient.getMake()->get() == nullptr); @@ -89,6 +85,12 @@ void Client::initThread(const char* desc, ServiceContext* service, AbstractMessa *currentClient.get() = service->makeClient(fullDesc, mp); } +void Client::destroy() { + invariant(currentClient.get()); + invariant(currentClient.get()->get()); + currentClient.reset(nullptr); +} + namespace { int64_t generateSeed(const std::string& desc) { size_t seed = 0; diff --git a/src/mongo/db/client.h b/src/mongo/db/client.h index 24cc847a430..5a500f4cf78 100644 --- a/src/mongo/db/client.h +++ b/src/mongo/db/client.h @@ -56,9 +56,15 @@ typedef long long ConnectionId; /** the database's concept of an outside "client" */ class Client : public ClientBasic { public: - /** each thread which does db operations has a Client object in TLS. - * call this when your thread starts. - */ + /** + * Creates a Client object and stores it in TLS for the current thread. + * + * An unowned pointer to a AbstractMessagingPort may optionally be provided. If 'mp' is + * non-null, then it will be used to augment the thread name, and for reporting purposes. + * + * If provided, 'mp' must outlive the newly-created Client object. Client::destroy() may be used + * to help enforce that the Client does not outlive 'mp'. + */ static void initThread(const char* desc, AbstractMessagingPort* mp = 0); static void initThread(const char* desc, ServiceContext* serviceContext, @@ -75,6 +81,15 @@ public: */ static void initThreadIfNotAlready(); + /** + * Destroys the Client object stored in TLS for the current thread. The current thread must have + * a Client. + * + * If destroy() is not called explicitly, then the Client stored in TLS will be destroyed upon + * exit of the current thread. + */ + static void destroy(); + std::string clientAddress(bool includePort = false) const; const std::string& desc() const { return _desc; diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index bb777862e0b..c56ffd6b248 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -202,6 +202,10 @@ public: break; } } + + virtual void close() { + Client::destroy(); + } }; static void logStartup(OperationContext* txn) { diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp index 3dcab21c098..00614a5f1cc 100644 --- a/src/mongo/s/server.cpp +++ b/src/mongo/s/server.cpp @@ -168,6 +168,10 @@ public: // Release connections back to pool, if any still cached ShardConnection::releaseMyConnections(); } + + virtual void close() { + Client::destroy(); + } }; DBClientBase* createDirectClient(OperationContext* txn) { diff --git a/src/mongo/util/net/message_server.h b/src/mongo/util/net/message_server.h index 5953ca4cdaa..47c545c4196 100644 --- a/src/mongo/util/net/message_server.h +++ b/src/mongo/util/net/message_server.h @@ -43,15 +43,21 @@ public: virtual ~MessageHandler() {} /** - * called once when a socket is connected + * Called once when a socket is connected. */ virtual void connected(AbstractMessagingPort* p) = 0; /** - * called every time a message comes in - * handler is responsible for responding to client + * Called every time a message comes in. Handler is responsible for responding to client. */ virtual void process(Message& m, AbstractMessagingPort* p) = 0; + + /** + * Called once, either when the client disconnects or when the process is shutting down. After + * close() is called, this handler's AbstractMessagingPort pointer (passed in via the + * connected() method) is no longer valid. + */ + virtual void close() = 0; }; class MessageServer { diff --git a/src/mongo/util/net/message_server_port.cpp b/src/mongo/util/net/message_server_port.cpp index 06c1fbc76e5..07a04756151 100644 --- a/src/mongo/util/net/message_server_port.cpp +++ b/src/mongo/util/net/message_server_port.cpp @@ -210,6 +210,7 @@ private: int64_t counter = 0; try { handler->connected(portWithHandler.get()); + ON_BLOCK_EXIT([handler]() { handler->close(); }); while (!inShutdown()) { m.reset(); @@ -222,7 +223,6 @@ private: log() << "end connection " << portWithHandler->psock->remoteString() << " (" << conns << word << " now open)" << endl; } - portWithHandler->shutdown(); break; } @@ -238,18 +238,16 @@ private: } catch (AssertionException& e) { log() << "AssertionException handling request, closing client connection: " << e << endl; - portWithHandler->shutdown(); } catch (SocketException& e) { log() << "SocketException handling request, closing client connection: " << e << endl; - portWithHandler->shutdown(); } catch (const DBException& e) { // must be right above std::exception to avoid catching subclasses log() << "DBException handling request, closing client connection: " << e << endl; - portWithHandler->shutdown(); } catch (std::exception& e) { error() << "Uncaught std::exception: " << e.what() << ", terminating" << endl; dbexit(EXIT_UNCAUGHT); } + portWithHandler->shutdown(); // Normal disconnect path. #ifdef MONGO_CONFIG_SSL |