You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by br...@apache.org on 2011/08/24 23:26:48 UTC

svn commit: r1161283 - in /thrift/trunk/lib/cpp/src/server: TNonblockingServer.cpp TNonblockingServer.h

Author: bryanduxbury
Date: Wed Aug 24 21:26:48 2011
New Revision: 1161283

URL: http://svn.apache.org/viewvc?rev=1161283&view=rev
Log:
THRIFT-1289. cpp: implement TNonblockingServer::stop() 

Patch: Adam Simpkins

Modified:
    thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp
    thrift/trunk/lib/cpp/src/server/TNonblockingServer.h

Modified: thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp?rev=1161283&r1=1161282&r2=1161283&view=diff
==============================================================================
--- thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp (original)
+++ thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp Wed Aug 24 21:26:48 2011
@@ -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 @@ 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<struct sockaddr*>(&addr), sizeof(addr));
+  close(fd);
+}
+
 }}} // apache::thrift::server

Modified: thrift/trunk/lib/cpp/src/server/TNonblockingServer.h
URL: http://svn.apache.org/viewvc/thrift/trunk/lib/cpp/src/server/TNonblockingServer.h?rev=1161283&r1=1161282&r2=1161283&view=diff
==============================================================================
--- thrift/trunk/lib/cpp/src/server/TNonblockingServer.h (original)
+++ thrift/trunk/lib/cpp/src/server/TNonblockingServer.h Wed Aug 24 21:26:48 2011
@@ -718,6 +718,11 @@ class TNonblockingServer : public TServe
    * 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