From 76c43688ba909af175e80635a5c38ff021cce7e5 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 24 Aug 2011 21:26:48 +0000 Subject: [PATCH] THRIFT-1289. cpp: implement TNonblockingServer::stop() Patch: Adam Simpkins git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1161283 13f79535-47bb-0310-9956-ffa450edef68 --- lib/cpp/src/server/TNonblockingServer.cpp | 42 ++++++++++++++++++++++- lib/cpp/src/server/TNonblockingServer.h | 5 +++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/cpp/src/server/TNonblockingServer.cpp b/lib/cpp/src/server/TNonblockingServer.cpp index 89e9afd7..550a5265 100644 --- a/lib/cpp/src/server/TNonblockingServer.cpp +++ b/lib/cpp/src/server/TNonblockingServer.cpp @@ -30,6 +30,7 @@ #ifdef HAVE_NETINET_IN_H #include #include +#include #endif #ifdef HAVE_NETDB_H @@ -919,8 +920,47 @@ void TNonblockingServer::serve() { eventHandler_->preServe(); } - // Run libevent engine, never returns, invokes calls to eventHandler + // Run libevent engine, invokes calls to eventHandler + // Only returns if stop() is called. event_base_loop(eventBase_, 0); } +void TNonblockingServer::stop() { + if (!eventBase_) { + return; + } + + // Call event_base_loopbreak() to tell libevent to exit the loop + // + // (The libevent documentation doesn't explicitly state that this function is + // safe to call from another thread. However, all it does is set a variable, + // in the event_base, so it should be fine.) + event_base_loopbreak(eventBase_); + + // event_base_loopbreak() only causes the loop to exit the next time it wakes + // up. We need to force it to wake up, in case there are no real events + // it needs to process. + // + // Attempt to connect to the server socket. If anything fails, + // we'll just have to wait until libevent wakes up on its own. + // + // First create a socket + int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { + return; + } + + // Set up the address + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 + addr.sin_port = htons(port_); + + // Finally do the connect(). + // We don't care about the return value; + // we're just going to close the socket either way. + connect(fd, reinterpret_cast(&addr), sizeof(addr)); + close(fd); +} + }}} // apache::thrift::server diff --git a/lib/cpp/src/server/TNonblockingServer.h b/lib/cpp/src/server/TNonblockingServer.h index 31741e40..20a33409 100644 --- a/lib/cpp/src/server/TNonblockingServer.h +++ b/lib/cpp/src/server/TNonblockingServer.h @@ -718,6 +718,11 @@ class TNonblockingServer : public TServer { * loops over the libevent handler. */ void serve(); + + /** + * May be called from a separate thread to cause serve() to return. + */ + void stop(); }; /// Three states for sockets: recv frame size, recv data, and send mode -- 2.17.1