From 93d06fc945c569fad0d662ddc06a31d0904be546 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Fri, 14 Feb 2014 17:25:53 +0400 Subject: [PATCH] Storinig exceptions in TLS: code review. --- src/box/lua/call.cc | 4 ++-- src/exception.cc | 50 ++++++++++++++++++++++++--------------------- src/exception.h | 4 ++++ src/fiber.cc | 6 ++++-- src/fiber.h | 4 ++-- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/box/lua/call.cc b/src/box/lua/call.cc index 786954c886..5f1003e8ca 100644 --- a/src/box/lua/call.cc +++ b/src/box/lua/call.cc @@ -340,9 +340,9 @@ lbox_raise(lua_State *L) { if (lua_gettop(L) == 0) { /* re-throw saved exceptions (if any) */ - if (cord()->exc == NULL) + if (cord()->exception == NULL) return 0; - cord()->exc->raise(); + cord()->exception->raise(); return 0; } diff --git a/src/exception.cc b/src/exception.cc index d048633690..64d739dc68 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -35,38 +35,42 @@ #include <errno.h> /* Statically allocate out-of-memory exception */ -static ClientError out_of_memory(__FILE__, __LINE__, ER_MEMORY_ISSUE, 0, +ClientError out_of_memory(__FILE__, __LINE__, ER_MEMORY_ISSUE, 0, "exception", "new"); -void* +void * Exception::operator new(size_t size) { - /* Explicity call destructor for previous exception */ - if (cord()->exc) - cord()->exc->~Exception(); - - /* Reuse memory allocated for exception */ - if (cord()->exc_size < size) { - size_t new_size = cord()->exc_size > 0 ? cord()->exc_size : 512; - while (new_size < size) - new_size *= 2; - void *exc = realloc(cord()->exc, new_size); - if (exc == NULL) - throw &out_of_memory; - cord()->exc = (Exception *) exc; - cord()->exc_size = new_size; - } + struct cord *cord = cord(); - return cord()->exc; + if (cord->exception == &out_of_memory) { + assert(cord->exception_size == 0); + cord->exception = NULL; + } + if (cord->exception) { + /* Explicitly call destructor for previous exception */ + cord->exception->~Exception(); + if (cord->exception_size >= size) { + /* Reuse memory allocated for exception */ + return cord->exception; + } + free(cord->exception); + } + cord->exception = (ClientError *) malloc(size); + if (cord->exception) { + cord->exception_size = size; + return cord->exception; + } + cord->exception = &out_of_memory; + cord->exception_size = 0; + throw cord->exception; } void -Exception::operator delete(void*) +Exception::operator delete(void * /* ptr */) { - /* Free memory allocated for exception */ - free(cord()->exc); - cord()->exc = NULL; - cord()->exc_size = 0; + /* Unsupported */ + assert(false); } Exception::Exception(const char *file, unsigned line) diff --git a/src/exception.h b/src/exception.h index dcf01dc226..a98317ed68 100644 --- a/src/exception.h +++ b/src/exception.h @@ -33,12 +33,14 @@ #include "errcode.h" #include "say.h" + class Exception: public Object { public: void *operator new(size_t size); void operator delete(void*); virtual void raise() { + /* Throw the most specific type of exception */ throw this; } @@ -119,6 +121,8 @@ class ClientError: public Exception { int m_errcode; }; +extern ClientError out_of_memory; + class LoggedError: public ClientError { public: template <typename ... Args> diff --git a/src/fiber.cc b/src/fiber.cc index 63fd8ccdb3..7042c3477b 100644 --- a/src/fiber.cc +++ b/src/fiber.cc @@ -527,8 +527,10 @@ cord_destroy(struct cord *cord) slab_cache_destroy(&cord->slabc); ev_loop_destroy(cord->loop); /* Cleanup memory allocated for exceptions */ - if (cord->exc) - delete cord->exc; + if (cord->exception && cord->exception != &out_of_memory) { + cord->exception->~Exception(); + free(cord->exception); + } } struct cord_thread_arg diff --git a/src/fiber.h b/src/fiber.h index e1a10de3b1..60e5e602c3 100644 --- a/src/fiber.h +++ b/src/fiber.h @@ -153,8 +153,8 @@ struct cord { struct slab_cache slabc; char name[FIBER_NAME_MAX]; /** Last thrown exception */ - struct Exception *exc; - size_t exc_size; + struct Exception *exception; + size_t exception_size; }; extern __thread struct cord *cord_ptr; -- GitLab