Fix error messages/unlimited CPU utilization.
authorBrian Aker <brian@tangent.org>
Thu, 14 Jun 2012 09:15:12 +0000 (05:15 -0400)
committerBrian Aker <brian@tangent.org>
Thu, 14 Jun 2012 09:15:12 +0000 (05:15 -0400)
libmemcached/io.cc
tests/libmemcached-1.0/all_tests.cc
tests/libmemcached-1.0/mem_functions.cc

index b08473a0c9bef42206d352c542f34a336c1549ad..defe234316adf3f8308f74c608253b6c4f885f8b 100644 (file)
@@ -205,7 +205,6 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
     return memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
   }
 
-  int local_errno;
   size_t loop_max= 5;
   while (--loop_max) // While loop is for ERESTART or EINTR
   {
@@ -213,27 +212,47 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
 
     if (active_fd >= 1)
     {
-      if (fds.revents & POLLHUP)
-      {
-        break;
-      }
-      assert_msg(active_fd == 1 , "poll() returned an unexpected value");
-      
+      assert_msg(active_fd == 1 , "poll() returned an unexpected number of active file descriptors");
       if (fds.revents & POLLIN or fds.revents & POLLOUT)
       {
         return MEMCACHED_SUCCESS;
       }
 
+      if (fds.revents & POLLHUP)
+      {
+        return memcached_set_error(*ptr, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
+                                   memcached_literal_param("poll() detected hang up"));
+      }
+
+      if (fds.revents & POLLERR)
+      {
+        int local_errno= EINVAL;
+        int err;
+        socklen_t len= sizeof (err);
+        if (getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len) == 0)
+        {
+          if (err == 0) // treat this as EINTR
+          {
+            continue;
+          }
+          local_errno= err;
+        }
+        memcached_quit_server(ptr, true);
+        return memcached_set_errno(*ptr, local_errno, MEMCACHED_AT,
+                                   memcached_literal_param("poll() returned POLLHUP"));
+      }
+      
       return memcached_set_error(*ptr, MEMCACHED_FAILURE, MEMCACHED_AT, memcached_literal_param("poll() returned a value that was not dealt with"));
     }
-    else if (active_fd == 0)
+
+    if (active_fd == 0)
     {
       ptr->io_wait_count.timeouts++;
       return memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
     }
 
     // Only an error should result in this code being called.
-    local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
+    int local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
     assert_msg(active_fd == -1 , "poll() returned an unexpected value");
     switch (local_errno)
     {
@@ -245,34 +264,27 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
 
     case EFAULT:
     case ENOMEM:
-      return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+      memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
 
     case EINVAL:
-      return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_literal_param("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"));
+      memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_literal_param("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"));
 
     default:
-      if (fds.revents & POLLERR)
-      {
-        int err;
-        socklen_t len= sizeof (err);
-        if (getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len) == 0)
-        {
-          if (err == 0) // treat this as EINTR
-          {
-            continue;
-          }
-          local_errno= err;
-        }
-      }
-      break;
+      memcached_set_errno(*ptr, local_errno, MEMCACHED_AT, memcached_literal_param("poll"));
     }
 
-    break; // should only occur from poll error
+    break;
   }
 
   memcached_quit_server(ptr, true);
 
-  return memcached_set_errno(*ptr, local_errno, MEMCACHED_AT);
+  if (memcached_has_error(ptr))
+  {
+    return memcached_server_error_return(ptr);
+  }
+
+  return memcached_set_error(*ptr, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
+                             memcached_literal_param("number of attempts to call io_wait() failed"));
 }
 
 static bool io_flush(memcached_server_write_instance_st ptr,
index 2efbdf27803f931a57c04e2bd6388bb92f8a69d0..bfa64c24aff64d5957df34b49e488ab16b35a808 100644 (file)
@@ -69,6 +69,8 @@
 
 #include "tests/libmemcached_world.h"
 
+#include <algorithm>
+
 void get_world(Framework *world)
 {
   if (getenv("LIBMEMCACHED_SERVER_NUMBER"))
@@ -79,8 +81,9 @@ void get_world(Framework *world)
   }
   else
   {
+    // Assume a minimum of 3, and a maximum of 8
     world->servers().set_servers_to_run(libtest::number_of_cpus() > 3 ? 
-                                        libtest::number_of_cpus() : 3);
+                                        std::min(libtest::number_of_cpus(), size_t(8)) : 3);
   }
 
   world->collections(collection);
index 2f6d56f36ed56cef7bc94815c9efd8456b81d20e..34d5e4b00f2db01b9c5b4c8ef69b35431abe5d68 100644 (file)
@@ -4394,10 +4394,10 @@ test_return_t regression_996813_TEST(memcached_st *)
   {
     test_compare(MEMCACHED_SUCCESS, memcached_server_add(memc, "10.2.3.4", base_port +x));
   }
-  test_compare(16U, memcached_generate_hash(memc, test_literal_param("SZ6hu0SHweFmpwpc0w2R")));
+  test_compare(6U, memcached_generate_hash(memc, test_literal_param("SZ6hu0SHweFmpwpc0w2R")));
   test_compare(1U, memcached_generate_hash(memc, test_literal_param("SQCK9eiCf53YxHWnYA.o")));
-  test_compare(10U, memcached_generate_hash(memc, test_literal_param("SUSDkGXuuZC9t9VhMwa.")));
-  test_compare(8U, memcached_generate_hash(memc, test_literal_param("SnnqnJARfaCNT679iAF_")));
+  test_compare(9U, memcached_generate_hash(memc, test_literal_param("SUSDkGXuuZC9t9VhMwa.")));
+  test_compare(0U, memcached_generate_hash(memc, test_literal_param("SnnqnJARfaCNT679iAF_")));
 
   memcached_free(memc);