From 19fae5d41322f8230ed5e0697ec0ce51e1ccdeaa Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Thu, 14 Jun 2012 05:15:12 -0400 Subject: [PATCH] Fix error messages/unlimited CPU utilization. --- libmemcached/io.cc | 66 +++++++++++++++---------- tests/libmemcached-1.0/all_tests.cc | 5 +- tests/libmemcached-1.0/mem_functions.cc | 6 +-- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/libmemcached/io.cc b/libmemcached/io.cc index b08473a0..defe2343 100644 --- a/libmemcached/io.cc +++ b/libmemcached/io.cc @@ -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, diff --git a/tests/libmemcached-1.0/all_tests.cc b/tests/libmemcached-1.0/all_tests.cc index 2efbdf27..bfa64c24 100644 --- a/tests/libmemcached-1.0/all_tests.cc +++ b/tests/libmemcached-1.0/all_tests.cc @@ -69,6 +69,8 @@ #include "tests/libmemcached_world.h" +#include + 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); diff --git a/tests/libmemcached-1.0/mem_functions.cc b/tests/libmemcached-1.0/mem_functions.cc index 2f6d56f3..34d5e4b0 100644 --- a/tests/libmemcached-1.0/mem_functions.cc +++ b/tests/libmemcached-1.0/mem_functions.cc @@ -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); -- 2.30.2