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
diff --git a/lib/cpp/src/server/TNonblockingServer.cpp b/lib/cpp/src/server/TNonblockingServer.cpp
index 89e9afd..550a526 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 <netinet/in.h>
 #include <netinet/tcp.h>
+#include <arpa/inet.h>
 #endif
 
 #ifdef HAVE_NETDB_H
@@ -919,8 +920,47 @@
     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<struct sockaddr*>(&addr), sizeof(addr));
+  close(fd);
+}
+
 }}} // apache::thrift::server