From: Michael Wallner Date: Fri, 10 Sep 2021 10:19:15 +0000 (+0200) Subject: fix #76: get returns NOTFOUND on TIMEOUT X-Git-Tag: 1.1.1~8 X-Git-Url: https://git.m6w6.name/?p=awesomized%2Flibmemcached;a=commitdiff_plain;h=9f88736f8219b494025465089655609f636bf1d7 fix #76: get returns NOTFOUND on TIMEOUT --- diff --git a/src/libmemcached/fetch.cc b/src/libmemcached/fetch.cc index d7feaca7..fee6a10d 100644 --- a/src/libmemcached/fetch.cc +++ b/src/libmemcached/fetch.cc @@ -141,6 +141,7 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, memcached_result_ memcached_instance_st *server; memcached_return_t read_ret = MEMCACHED_SUCCESS; bool connection_failures = false; + bool timeouts = false; while ((server = memcached_io_get_readable_server(ptr, read_ret))) { char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; *error = memcached_response(server, buffer, sizeof(buffer), result); @@ -150,6 +151,8 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, memcached_result_ } else if (*error == MEMCACHED_CONNECTION_FAILURE) { connection_failures = true; continue; + } else if (*error == MEMCACHED_TIMEOUT) { + timeouts = true; } else if (*error == MEMCACHED_SUCCESS) { result->count++; return result; @@ -175,6 +178,8 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr, memcached_result_ that. */ *error = MEMCACHED_CONNECTION_FAILURE; + } else if (timeouts) { + *error = MEMCACHED_TIMEOUT; } else if (*error == MEMCACHED_SUCCESS) { *error = MEMCACHED_END; } else if (result->count == 0) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6e64777a..523db5be 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,6 +45,8 @@ if(NOT MEMCACHED_BINARY) set(ENV{INVALID_CONFIGURATION} 1) endif() +add_executable(timeout timeout.c) + file(GLOB_RECURSE TESTING_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) set(TESTING_ROOT "${CMAKE_CURRENT_BINARY_DIR}") set(SOURCES_ROOT "${CMAKE_SOURCE_DIR}") @@ -66,7 +68,7 @@ if(NOT (thread IN_LIST ENABLE_SANITIZERS)) endif() endif() -add_dependencies(runtests ${CLIENTS}) +add_dependencies(runtests ${CLIENTS} timeout) if(TARGET memaslap) configure_set(HAVE_MEMASLAP 1) add_dependencies(runtests memaslap) diff --git a/test/tests/memcached/regression/lp_001-540-680.cpp b/test/tests/memcached/regression/lp_001-540-680.cpp new file mode 100644 index 00000000..85cd70a1 --- /dev/null +++ b/test/tests/memcached/regression/lp_001-540-680.cpp @@ -0,0 +1,20 @@ +#include "test/lib/common.hpp" +#include "test/lib/random.hpp" +#include "test/lib/Server.hpp" +#include "test/lib/ReturnMatcher.hpp" + +TEST_CASE("memcached_regression_lp1540680") { + Server timeout{TESTING_ROOT "/timeout", {"-p", random_port_string}}; + MemcachedPtr memc; + LoneReturnMatcher test{*memc}; + + REQUIRE(timeout.start()); + this_thread::sleep_for(500ms); + + REQUIRE_SUCCESS(memcached_server_add(*memc, "localhost", get(timeout.getSocketOrPort()))); + + memcached_return_t rc; + Malloced val(memcached_get(*memc, S("not-found"), nullptr, nullptr, &rc)); + REQUIRE_RC(MEMCACHED_TIMEOUT, rc); + REQUIRE_FALSE(*val); +} diff --git a/test/timeout.c b/test/timeout.c new file mode 100644 index 00000000..e3c59a3a --- /dev/null +++ b/test/timeout.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include + +// $0 -u nobody -p +int main(int argc, char **argv) { + short port = argc == 5 ? atoi(argv[4]) : 11211; + struct sockaddr_in servaddr; + memset(&servaddr, 0, sizeof(struct sockaddr_in)); + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htons(INADDR_ANY); + servaddr.sin_port = htons(port); + + int listen_fd = socket(AF_INET, SOCK_STREAM, 0); + bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)); + listen(listen_fd, 10); + printf("Listening (%d) on port %d\n", listen_fd, port); + + int comm_fd = accept(listen_fd, NULL, NULL); + printf("Connection (%d) accepted, now do nothing...\n", comm_fd); + + pause(); +}