while (--loop_max) // Should only loop on cases of ERESTART or EINTR
{
- error= poll(fds, 1, ptr->root->connect_timeout);
+ if (ptr->root->poll_timeout)
+ {
+ error= poll(fds, 1, ptr->root->connect_timeout);
+ }
+ else
+ {
+ error= 0;
+ }
switch (error)
{
}
case 0:
return MEMCACHED_TIMEOUT;
+
default: // A real error occurred and we need to completely bail
WATCHPOINT_ERRNO(get_socket_errno());
switch (get_socket_errno())
case EINPROGRESS: // nonblocking mode - first return
case EALREADY: // nonblocking mode - subsequent returns
{
- memcached_return_t rc;
- rc= connect_poll(ptr);
+ memcached_return_t rc= connect_poll(ptr);
if (rc == MEMCACHED_TIMEOUT)
timeout_error_occured= true;
rc= MEMCACHED_ERRNO;
}
+ if (rc == MEMCACHED_ERRNO and local_errno == ENOTCONN)
+ {
+ rc= MEMCACHED_CONNECTION_FAILURE;
+ }
+
memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
if (not error) // Bad business if this happens
return;
error->rc= rc;
error->local_errno= local_errno;
- if (str)
+ if (str and local_errno)
+ {
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s), %.*s -> %s",
+ memcached_strerror(&memc, rc),
+ strerror(local_errno),
+ int(error->size), str->c_str, at);
+ }
+ else if (local_errno)
+ {
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s(%s) -> %s",
+ memcached_strerror(&memc, rc),
+ strerror(local_errno), at);
+ }
+ else if (str)
{
- size_t length= str->size > (size_t)MAX_ERROR_LENGTH ? MAX_ERROR_LENGTH : str->size;
- error->size= length;
- memcpy(error->message, str->c_str, error->size);
- error->message[error->size]= 0;
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s, %.*s -> %s",
+ memcached_strerror(&memc, rc),
+ int(error->size), str->c_str, at);
}
else
{
- error->size= 0;
+ error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "%s -> %s",
+ memcached_strerror(&memc, rc), at);
}
error->next= memc.error_messages;
*/
-#include "libmemcached/common.h"
+#include <libmemcached/common.h>
typedef enum {
MEM_READ,
{
memcached_return_t rc= memcached_purge(ptr);
if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
+ {
return MEMCACHED_FAILURE;
+ }
}
size_t loop_max= 5;
while (--loop_max) // While loop is for ERESTART or EINTR
{
- error= poll(&fds, 1, ptr->root->poll_timeout);
+ if (ptr->root->poll_timeout) // Mimic 0 causes timeout behavior (not all platforms do this)
+ {
+ error= poll(&fds, 1, ptr->root->poll_timeout);
+ }
+ else
+ {
+ error= 0;
+ }
switch (error)
{
WATCHPOINT_IF_LABELED_NUMBER(!read_or_write && loop_max < 4, "write() times we had to loop, decremented down from 5", loop_max);
return MEMCACHED_SUCCESS;
+
case 0: // Timeout occured, we let the while() loop do its thing.
- return MEMCACHED_TIMEOUT;
+ return memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
+
default:
WATCHPOINT_ERRNO(get_socket_errno());
switch (get_socket_errno())
#endif
case EINTR:
break;
+
default:
if (fds.revents & POLLERR)
{
}
memcached_quit_server(ptr, true);
- return MEMCACHED_FAILURE;
+ return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
}
}
}
ptr->cached_errno= get_socket_errno();
memcached_quit_server(ptr, true);
- return MEMCACHED_FAILURE;
+ return memcached_set_error(*ptr, MEMCACHED_FAILURE, MEMCACHED_AT);
}
memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr)
#endif
if ((rc= io_wait(ptr, MEM_READ)) == MEMCACHED_SUCCESS)
continue;
+
/* fall through */
default:
// UDP Sanity check, make sure that we are not sending somthing too big
if (ptr->type == MEMCACHED_CONNECTION_UDP && write_length > MAX_UDP_DATAGRAM_LENGTH)
{
+ *error= MEMCACHED_WRITE_FAILURE;
return -1;
}
if (ptr->write_buffer_offset == 0 || (ptr->type == MEMCACHED_CONNECTION_UDP
&& ptr->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH))
+ {
return 0;
+ }
/* Looking for memory overflows */
#if defined(DEBUG)
process_input_buffer(ptr))
continue;
- memcached_return_t rc;
- rc= io_wait(ptr, MEM_WRITE);
-
- if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_TIMEOUT)
+ memcached_return_t rc= io_wait(ptr, MEM_WRITE);
+ if (memcached_success(rc))
{
continue;
}
+ else if (rc == MEMCACHED_TIMEOUT)
+ {
+ *error= memcached_set_error(*ptr, MEMCACHED_TIMEOUT, MEMCACHED_AT);
+ return -1;
+ }
memcached_quit_server(ptr, true);
+ *error= memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
return -1;
}
case ENOTCONN:
}
}
- if (ptr->type == MEMCACHED_CONNECTION_UDP &&
+ if (ptr->type == MEMCACHED_CONNECTION_UDP and
(size_t)sent_length != write_length)
{
memcached_quit_server(ptr, true);
+ *error= memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
return -1;
}
memcached_return_t memcached_purge(memcached_server_write_instance_st ptr)
{
- uint32_t x;
memcached_return_t ret= MEMCACHED_SUCCESS;
memcached_st *root= (memcached_st *)ptr->root;
{
memcached_set_purging(root, true);
- return MEMCACHED_WRITE_FAILURE;
+ return memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
}
WATCHPOINT_ASSERT(ptr->fd != -1);
result_ptr= memcached_result_create(root, &result);
WATCHPOINT_ASSERT(result_ptr);
- for (x= 0; x < no_msg; x++)
+ for (uint32_t x= 0; x < no_msg; x++)
{
memcached_result_reset(result_ptr);
memcached_return_t rc= memcached_read_one_response(ptr, buffer,
if (rc== MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_UNKNOWN_READ_FAILURE)
{
WATCHPOINT_ERROR(rc);
- ret = rc;
+ ret= rc;
memcached_io_reset(ptr);
+ memcached_set_error(*ptr, rc, MEMCACHED_AT);
}
if (ptr->root->callbacks != NULL)
MEMCACHED_SUCCESS,
MEMCACHED_FAILURE,
MEMCACHED_HOST_LOOKUP_FAILURE, // getaddrinfo() and getnameinfo() only
- MEMCACHED_CONNECTION_FAILURE, // DEPRECATED
- MEMCACHED_CONNECTION_BIND_FAILURE, // DEPRECATED
+ MEMCACHED_CONNECTION_FAILURE,
+ MEMCACHED_CONNECTION_BIND_FAILURE, // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE
MEMCACHED_WRITE_FAILURE,
MEMCACHED_READ_FAILURE,
MEMCACHED_UNKNOWN_READ_FAILURE,
}
if (argc > 1)
+ {
collection_to_run= argv[1];
+ }
+ else if (getenv("TEST_COLLECTION"))
+ {
+ collection_to_run= getenv("TEST_COLLECTION");
+ }
+
+ if (collection_to_run)
+ printf("Only testing %s\n", collection_to_run);
if (argc == 3)
+ {
wildcard= argv[2];
+ }
for (next= collection; next->name; next++)
{
test_false(value);
test_compare(0, length);
- test_true_got(rc == MEMCACHED_TIMEOUT || rc == MEMCACHED_ERRNO || rc == MEMCACHED_FAILURE, memcached_strerror(memc, rc));
+ test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_strerror(memc, rc));
memcached_free(memc);
{"lp:?", 1, (test_callback_fn)regression_bug_ },
{"lp:728286", 1, (test_callback_fn)regression_bug_728286 },
{"lp:581030", 1, (test_callback_fn)regression_bug_581030 },
- {"lp:71231153", 1, (test_callback_fn)regression_bug_71231153 },
+ {"lp:71231153 connect()", 1, (test_callback_fn)regression_bug_71231153_connect },
+ {"lp:71231153 poll()", 1, (test_callback_fn)regression_bug_71231153_poll },
{0, 0, (test_callback_fn)0}
};
return TEST_SUCCESS;
}
-test_return_t regression_bug_71231153(memcached_st *)
+/*
+ By setting the timeout value to zero, we force poll() to return immediatly.
+*/
+test_return_t regression_bug_71231153_connect(memcached_st *)
{
if (libmemcached_util_ping("10.0.2.252", 0, NULL)) // If for whatever reason someone has a host at this address, skip
return TEST_SKIPPED;
- memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --CONNECT-TIMEOUT=1 --POLL-TIMEOUT=1"));
- test_true(memc);
- test_compare(1, memc->connect_timeout);
- test_compare(1, memc->poll_timeout);
+ { // Test the connect-timeout, on a bad host we should get MEMCACHED_CONNECTION_FAILURE
+ memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --CONNECT-TIMEOUT=0"));
+ test_true(memc);
+ test_compare(0, memc->connect_timeout);
+ test_compare(MEMCACHED_DEFAULT_TIMEOUT, memc->poll_timeout);
- memcached_return_t rc;
- size_t value_len;
- char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc);
- test_false(value);
- test_compare(0, value_len);
- test_true_got(rc == MEMCACHED_TIMEOUT or rc == MEMCACHED_FAILURE or rc == MEMCACHED_ERRNO, memcached_strerror(memc, rc));
+ memcached_return_t rc;
+ size_t value_len;
+ char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc);
+ test_false(value);
+ test_compare(0, value_len);
+ test_compare_got(MEMCACHED_CONNECTION_FAILURE, rc, memcached_strerror(NULL, rc));
- memcached_free(memc);
+ memcached_free(memc);
+ }
+
+ return TEST_SUCCESS;
+}
+
+test_return_t regression_bug_71231153_poll(memcached_st *)
+{
+ if (libmemcached_util_ping("10.0.2.252", 0, NULL)) // If for whatever reason someone has a host at this address, skip
+ return TEST_SKIPPED;
+
+ { // Test the poll timeout, on a bad host we should get MEMCACHED_CONNECTION_FAILURE
+ memcached_st *memc= memcached(memcached_literal_param("--SERVER=10.0.2.252 --POLL-TIMEOUT=0"));
+ test_true(memc);
+ test_compare(MEMCACHED_DEFAULT_CONNECT_TIMEOUT, memc->connect_timeout);
+ test_compare(0, memc->poll_timeout);
+
+ memcached_return_t rc;
+ size_t value_len;
+ char *value= memcached_get(memc, memcached_literal_param("test"), &value_len, NULL, &rc);
+ test_false(value);
+ test_compare(0, value_len);
+ test_compare_got(MEMCACHED_TIMEOUT, rc, memcached_strerror(NULL, rc));
+
+ memcached_free(memc);
+ }
return TEST_SUCCESS;
}
test_return_t test_hostname_port_weight(memcached_st *);
LIBTEST_INTERNAL_API
-test_return_t regression_bug_71231153(memcached_st *);
+test_return_t regression_bug_71231153_connect(memcached_st *);
+
+LIBTEST_INTERNAL_API
+test_return_t regression_bug_71231153_poll(memcached_st *);
#ifdef __cplusplus
}