You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by dr...@apache.org on 2010/03/09 06:19:35 UTC

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

Author: dreiss
Date: Tue Mar  9 05:19:34 2010
New Revision: 920668

URL: http://svn.apache.org/viewvc?rev=920668&view=rev
Log:
cpp: Fix for task completion notification deadlock under heavy server load

Along with insuring that the event loop is able to see task completion
notifications, we need to process pending notifications as soon as they
are available to avoid filling the notification pipe (the pipe can hold
512 notifications).

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

Modified: incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp?rev=920668&r1=920667&r2=920668&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp (original)
+++ incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.cpp Tue Mar  9 05:19:34 2010
@@ -570,12 +570,12 @@ void TNonblockingServer::handleEvent(int
       nTotalConnectionsDropped_++;
       if (overloadAction_ == T_OVERLOAD_CLOSE_ON_ACCEPT) {
         close(clientSocket);
-        continue;
+        return;
       } else if (overloadAction_ == T_OVERLOAD_DRAIN_TASK_QUEUE) {
         if (!drainPendingTask()) {
           // Nothing left to discard, so we drop connection instead.
           close(clientSocket);
-          continue;
+          return;
         }
       }
     }
@@ -718,6 +718,13 @@ void TNonblockingServer::createNotificat
     GlobalOutput.perror("TNonblockingServer::createNotificationPipe ", errno);
       throw TException("can't create notification pipe");
   }
+  int flags;
+  if ((flags = fcntl(notificationPipeFDs_[0], F_GETFL, 0)) < 0 ||
+      fcntl(notificationPipeFDs_[0], F_SETFL, flags | O_NONBLOCK) < 0) {
+    close(notificationPipeFDs_[0]);
+    close(notificationPipeFDs_[1]);
+    throw TException("TNonblockingServer::createNotificationPipe() O_NONBLOCK");
+  }
 }
 
 /**

Modified: incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.h
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.h?rev=920668&r1=920667&r2=920668&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.h (original)
+++ incubator/thrift/trunk/lib/cpp/src/server/TNonblockingServer.h Tue Mar  9 05:19:34 2010
@@ -722,13 +722,17 @@ class TConnection {
    */
   static void taskHandler(int fd, short /* which */, void* /* v */) {
     TConnection* connection;
-    if (read(fd, (void*)&connection, sizeof(TConnection*))
-        != sizeof(TConnection*)) {
+    ssize_t nBytes;
+    while ((nBytes = read(fd, (void*)&connection, sizeof(TConnection*)))
+        == sizeof(TConnection*)) {
+      connection->transition();
+    }
+    if (nBytes > 0) {
+      throw TException("TConnection::taskHandler unexpected partial read");
+    }
+    if (errno != EWOULDBLOCK && errno != EAGAIN) {
       GlobalOutput.perror("TConnection::taskHandler read failed, resource leak", errno);
-      return;
     }
-
-    connection->transition();
   }
 
   /**