From: Brian Aker Date: Wed, 10 Feb 2010 17:00:45 +0000 (-0800) Subject: bug fix for recursive decent into quit() X-Git-Tag: 0.40~50 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=70c3fdd7d6d441a8be3e831f6a0aa3ae88166bc6;p=m6w6%2Flibmemcached bug fix for recursive decent into quit() --- diff --git a/ChangeLog b/ChangeLog index a3024f14..5012b84c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,7 @@ * Many fixes to memslap. * Updates for memcapable. * Compile fixes for OpenBSD. +* Fix for possible recursive decent on IO failure. 0.37 Mon Jan 11 16:29:57 PST 2010 * Fixed build for libhashkit. diff --git a/libmemcached/io.c b/libmemcached/io.c index 6f5f3d23..ef46a0d9 100644 --- a/libmemcached/io.c +++ b/libmemcached/io.c @@ -64,14 +64,14 @@ static memcached_return_t io_wait(memcached_server_instance_st *ptr, return MEMCACHED_SUCCESS; case 0: return MEMCACHED_TIMEOUT; -#if TARGET_OS_LINUX +#ifdef TARGET_OS_LINUX case ERESTART: #endif case EINTR: continue; default: ptr->cached_errno= error; - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); return MEMCACHED_FAILURE; } @@ -80,7 +80,7 @@ static memcached_return_t io_wait(memcached_server_instance_st *ptr, /* Imposssible for anything other then -1 */ WATCHPOINT_ASSERT(error == -1); ptr->cached_errno= error; - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); return MEMCACHED_FAILURE; } @@ -260,7 +260,7 @@ memcached_return_t memcached_io_read(memcached_server_instance_st *ptr, { case EAGAIN: case EINTR: -#if TARGET_OS_LINUX +#ifdef TARGET_OS_LINUX case ERESTART: #endif if ((rc= io_wait(ptr, MEM_READ)) == MEMCACHED_SUCCESS) @@ -269,7 +269,7 @@ memcached_return_t memcached_io_read(memcached_server_instance_st *ptr, default: { - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); *nread= -1; return rc; } @@ -286,7 +286,7 @@ memcached_return_t memcached_io_read(memcached_server_instance_st *ptr, for blocking I/O we do not return 0 and for non-blocking case it will return EGAIN if data is not immediatly available. */ - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); *nread= -1; return MEMCACHED_UNKNOWN_READ_FAILURE; } @@ -569,11 +569,11 @@ static ssize_t io_flush(memcached_server_instance_st *ptr, if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_TIMEOUT) continue; - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); return -1; } default: - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); *error= MEMCACHED_ERRNO; return -1; } @@ -582,7 +582,7 @@ static ssize_t io_flush(memcached_server_instance_st *ptr, if (ptr->type == MEMCACHED_CONNECTION_UDP && (size_t)sent_length != write_length) { - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); return -1; } @@ -612,7 +612,7 @@ static ssize_t io_flush(memcached_server_instance_st *ptr, */ void memcached_io_reset(memcached_server_instance_st *ptr) { - memcached_quit_server(ptr, 1); + memcached_quit_server(ptr, true); } /** diff --git a/libmemcached/quit.c b/libmemcached/quit.c index 8b5acf67..292bc6e4 100644 --- a/libmemcached/quit.c +++ b/libmemcached/quit.c @@ -13,11 +13,13 @@ void memcached_quit_server(memcached_server_st *ptr, bool io_death) { if (ptr->fd != -1) { - if (io_death == false && ptr->type != MEMCACHED_CONNECTION_UDP) + if (io_death == false && ptr->type != MEMCACHED_CONNECTION_UDP && ptr->options.is_shutting_down == false) { memcached_return_t rc; char buffer[MEMCACHED_MAX_BUFFER]; + ptr->options.is_shutting_down= true; + if (ptr->root->flags.binary_protocol) { protocol_binary_request_quit request = {.bytes= {0}}; @@ -59,6 +61,7 @@ void memcached_quit_server(memcached_server_st *ptr, bool io_death) ptr->write_buffer_offset= (size_t) ((ptr->type == MEMCACHED_CONNECTION_UDP) ? UDP_DATAGRAM_HEADER_LENGTH : 0); ptr->read_buffer_length= 0; ptr->read_ptr= ptr->read_buffer; + ptr->options.is_shutting_down= false; memcached_server_response_reset(ptr); if (io_death) @@ -81,7 +84,7 @@ void memcached_quit(memcached_st *ptr) memcached_server_instance_st *instance= memcached_server_instance_fetch(ptr, x); - memcached_quit_server(instance, 0); + memcached_quit_server(instance, false); } } } diff --git a/libmemcached/server.c b/libmemcached/server.c index 6fd685fe..f480750d 100644 --- a/libmemcached/server.c +++ b/libmemcached/server.c @@ -19,6 +19,7 @@ static inline void _server_init(memcached_server_st *self, const memcached_st *r uint32_t weight, memcached_connection_t type) { self->options.sockaddr_inited= false; + self->options.is_shutting_down= false; self->number_of_hosts= 0; self->cursor_active= 0; self->port= port; @@ -100,7 +101,7 @@ memcached_server_st *memcached_server_create_with(const memcached_st *memc, memc void memcached_server_free(memcached_server_st *self) { - memcached_quit_server(self, 0); + memcached_quit_server(self, false); if (self->cached_server_error) free(self->cached_server_error); diff --git a/libmemcached/server.h b/libmemcached/server.h index 109f9d50..51747528 100644 --- a/libmemcached/server.h +++ b/libmemcached/server.h @@ -18,6 +18,7 @@ struct memcached_server_st { bool is_allocated MEMCACHED_BITFIELD; bool is_initialized MEMCACHED_BITFIELD; bool sockaddr_inited MEMCACHED_BITFIELD; + bool is_shutting_down MEMCACHED_BITFIELD; } options; uint32_t number_of_hosts; uint32_t cursor_active;