THRIFT-2838 TNonblockingServer can bind to port 0 (i.e., get an OS-assigned port) but there is no way to get the port number
diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp
index 9833f10..a952bf0 100644
--- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp
+++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp
@@ -1099,6 +1099,16 @@
 
   // Cool, this socket is good to go, set it as the serverSocket_
   serverSocket_ = s;
+
+  if (!port_) {
+    sockaddr_in addr;
+    unsigned int size = sizeof(addr);
+    if (!getsockname(serverSocket_, reinterpret_cast<sockaddr*>(&addr), &size)) {
+      listenPort_ = ntohs(addr.sin_port);
+    } else {
+      GlobalOutput.perror("TNonblocking: failed to get listen port: ", THRIFT_GET_SOCKET_ERROR);
+    }
+  }
 }
 
 void TNonblockingServer::setThreadManager(boost::shared_ptr<ThreadManager> threadManager) {
@@ -1157,6 +1167,9 @@
 }
 
 void TNonblockingServer::stop() {
+  if (!port_) {
+    listenPort_ = 0;
+  }
   // Breaks the event loop in all threads so that they end ASAP.
   for (uint32_t i = 0; i < ioThreads_.size(); ++i) {
     ioThreads_[i]->stop();
@@ -1196,7 +1209,7 @@
   assert(ioThreads_.size() > 0);
 
   GlobalOutput.printf("TNonblockingServer: Serving on port %d, %d io threads.",
-                      port_,
+                      listenPort_,
                       ioThreads_.size());
 
   // Launch all the secondary IO threads in separate threads
diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.h b/lib/cpp/src/thrift/server/TNonblockingServer.h
index 3edc795..4f23487 100644
--- a/lib/cpp/src/thrift/server/TNonblockingServer.h
+++ b/lib/cpp/src/thrift/server/TNonblockingServer.h
@@ -155,9 +155,12 @@
   /// Server socket file descriptor
   THRIFT_SOCKET serverSocket_;
 
-  /// Port server runs on
+  /// Port server runs on. Zero when letting OS decide actual port
   int port_;
 
+  /// Port server actually runs on
+  int listenPort_;
+
   /// The optional user-provided event-base (for single-thread servers)
   event_base* userEventBase_;
 
@@ -280,6 +283,7 @@
     nextIOThread_ = 0;
     useHighPriorityIOThreads_ = false;
     port_ = port;
+    listenPort_ = port;
     userEventBase_ = NULL;
     threadPoolProcessing_ = false;
     numTConnections_ = 0;
@@ -395,6 +399,8 @@
 
   void setThreadManager(boost::shared_ptr<ThreadManager> threadManager);
 
+  int getListenPort() { return listenPort_; }
+
   boost::shared_ptr<ThreadManager> getThreadManager() { return threadManager_; }
 
   /**