summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/client/scoped_db_conn_test.cpp2
-rw-r--r--src/mongo/db/client.cpp10
-rw-r--r--src/mongo/db/client.h21
-rw-r--r--src/mongo/db/db.cpp4
-rw-r--r--src/mongo/s/server.cpp4
-rw-r--r--src/mongo/util/net/message_server.h12
-rw-r--r--src/mongo/util/net/message_server_port.cpp6
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