From 250d031a103fafac805fcf28bccf2120cc936994 Mon Sep 17 00:00:00 2001 From: Roman Tsisyk <roman@tsisyk.com> Date: Wed, 12 Feb 2014 17:45:03 +0400 Subject: [PATCH] Explicitly use thread-local buffer for C++ exceptions This patch explicitly saves Exception to a thread-local variable inside struct cord on tnt_raise(). This variable can be used to safetly re-throw last exception from any place (not only from catch() block). This technique requires exception to be thrown and catched by pointers. tnt_raise macros was rewritten and all 'catch (Exception &)' blocks were substituted with 'catch (Exception *e)'. This patch also adds a new feature to box.raise() function. When called without arguments box.raise() re-throws last exception (if any). These changes needed to implement proper handlings of exception for FFI calls. --- client/tarantar/update.cc | 2 +- doc/user/stored-procedures.xml | 2 ++ src/box/bitset_index.cc | 2 +- src/box/box.cc | 6 +++--- src/box/lua/call.cc | 12 ++++++++++-- src/box/lua/tuple.cc | 2 +- src/box/space.cc | 2 +- src/box/tuple.cc | 2 +- src/coio.cc | 6 +++--- src/evio.cc | 8 ++++---- src/exception.cc | 36 ++++++++++++++++++++++++++++++++++ src/exception.h | 5 ++++- src/fiber.cc | 9 ++++++--- src/fiber.h | 4 ++++ src/iproto.cc | 22 ++++++++++----------- src/iproto_port.cc | 9 ++++----- src/iproto_port.h | 2 +- src/lua/fiber.cc | 14 ++++++------- src/lua/init.cc | 10 +++++----- src/lua/socket.cc | 22 ++++++++++----------- src/lua/utils.h | 2 +- src/recovery.cc | 2 +- src/replica.cc | 8 ++++---- src/session.cc | 6 +++--- src/tarantool.cc | 5 +++-- test/box/misc.result | 17 ++++++++++++++++ test/box/misc.test.lua | 10 ++++++++++ 27 files changed, 155 insertions(+), 72 deletions(-) diff --git a/client/tarantar/update.cc b/client/tarantar/update.cc index e787d9fbfc..36cc671ecd 100644 --- a/client/tarantar/update.cc +++ b/client/tarantar/update.cc @@ -94,7 +94,7 @@ ts_update(struct tnt_request *r, struct tnt_tuple *old) memset(buf, 0, new_size); tuple_update_execute(u, (char*)buf); - } catch (const Exception&) { + } catch (Exception *e) { if (buf) free(buf); region_reset(&tss.ra); diff --git a/doc/user/stored-procedures.xml b/doc/user/stored-procedures.xml index 408a4ef8b1..42316b6092 100644 --- a/doc/user/stored-procedures.xml +++ b/doc/user/stored-procedures.xml @@ -1118,6 +1118,8 @@ localhost> <userinput>setopt delimiter=''!</userinput> message can be arbitrary. Lua procedures can use <code>box.raise()</code> to emulate request errors (for example: unique key exception). + When called without arguments this function re-throws last + thrown error. </para> <para> Parameters: <code>errcode-number</code> = number taken from the complete list of errors, diff --git a/src/box/bitset_index.cc b/src/box/bitset_index.cc index 6f085fcd19..0b9f9b2be5 100644 --- a/src/box/bitset_index.cc +++ b/src/box/bitset_index.cc @@ -259,7 +259,7 @@ BitsetIndex::initIterator(struct iterator *iterator, enum iterator_type type, } bitset_expr_destroy(&expr); - } catch (const Exception& e) { + } catch (Exception *e) { bitset_expr_destroy(&expr); throw; } diff --git a/src/box/box.cc b/src/box/box.cc index ba395c1368..1a75a8b4bc 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -91,7 +91,7 @@ process_rw(struct port *port, struct request *request) port_send_tuple(port, txn); port_eof(port); txn_finish(txn); - } catch (const Exception& e) { + } catch (Exception *e) { txn_rollback(txn); throw; } @@ -126,8 +126,8 @@ recover_row(void *param __attribute__((unused)), const struct log_row *row) request_create(&request, op); request_decode(&request, data, end - data); process_rw(&null_port, &request); - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); return -1; } diff --git a/src/box/lua/call.cc b/src/box/lua/call.cc index 51d0baaeba..7ff4224ff0 100644 --- a/src/box/lua/call.cc +++ b/src/box/lua/call.cc @@ -231,7 +231,7 @@ lbox_process(lua_State *L) * use fiber->cleanup and fiber->gc. */ region_truncate(&fiber()->gc, allocated_size); - } catch (const Exception &e) { + } catch (Exception *e) { region_truncate(&fiber()->gc, allocated_size); throw; } @@ -338,7 +338,15 @@ lbox_delete(lua_State *L) static int lbox_raise(lua_State *L) { - if (lua_gettop(L) != 2) + if (lua_gettop(L) == 0) { + /* re-throw saved exceptions (if any) */ + if (cord()->exc == NULL) + return 0; + throw cord()->exc; + return 0; + } + + if (lua_gettop(L) < 2) luaL_error(L, "box.raise(): bad arguments"); uint32_t code = lua_tointeger(L, 1); if (!code) diff --git a/src/box/lua/tuple.cc b/src/box/lua/tuple.cc index b21548b860..5c71c113b2 100644 --- a/src/box/lua/tuple.cc +++ b/src/box/lua/tuple.cc @@ -581,7 +581,7 @@ lua_totuple(struct lua_State *L, int first, int last) struct tbuf *b = tbuf_new(&fiber()->gc); try { luamp_encodestack(L, b, first, last); - } catch (const Exception &e) { + } catch (Exception *e) { throw; } catch (...) { tnt_raise(ClientError, ER_PROC_LUA, lua_tostring(L, -1)); diff --git a/src/box/space.cc b/src/box/space.cc index f431db99ae..c484bb2255 100644 --- a/src/box/space.cc +++ b/src/box/space.cc @@ -183,7 +183,7 @@ space_replace_all_keys(struct space *space, struct tuple *old_tuple, index->replace(old_tuple, new_tuple, DUP_INSERT); } return old_tuple; - } catch (const Exception &e) { + } catch (Exception *e) { /* Rollback all changes */ for (; i > 0; i--) { Index *index = space->index[i-1]; diff --git a/src/box/tuple.cc b/src/box/tuple.cc index 6bc690c8ca..c509a545a0 100644 --- a/src/box/tuple.cc +++ b/src/box/tuple.cc @@ -395,7 +395,7 @@ tuple_update(struct tuple_format *format, try { tuple_init_field_map(format, new_tuple, (uint32_t *)new_tuple); - } catch (const Exception&) { + } catch (Exception *e) { tuple_delete(new_tuple); throw; } diff --git a/src/coio.cc b/src/coio.cc index 77e000186c..519909767e 100644 --- a/src/coio.cc +++ b/src/coio.cc @@ -155,7 +155,7 @@ coio_connect_addrinfo(struct ev_io *coio, struct addrinfo *ai, if (res) evio_close(loop, coio); return res; - } catch (const SocketError& e) { + } catch (SocketError *e) { if (res) evio_close(loop, coio); if (ai->ai_next == NULL) @@ -376,7 +376,7 @@ coio_flush(int fd, struct iovec *iov, ssize_t offset, int iovcnt) sio_add_to_iov(iov, -offset); nwr = sio_writev(fd, iov, iovcnt); sio_add_to_iov(iov, offset); - } catch (const Exception& e) { + } catch (Exception *e) { sio_add_to_iov(iov, offset); throw; } @@ -542,7 +542,7 @@ coio_service_on_accept(struct evio_service *evio_service, try { iobuf = iobuf_new(iobuf_name); f = fiber_new(fiber_name, service->handler); - } catch (const Exception& e) { + } catch (Exception *e) { say_error("can't create a handler fiber, dropping client connection"); evio_close(loop(), &coio); if (iobuf) diff --git a/src/evio.cc b/src/evio.cc index 73b0709abc..962c040587 100644 --- a/src/evio.cc +++ b/src/evio.cc @@ -151,7 +151,7 @@ evio_bind_addrinfo(struct ev_io *evio, struct addrinfo *ai) return; /* success. */ } assert(errno == EADDRINUSE); - } catch (const SocketError& e) { + } catch (SocketError *e) { if (ai->ai_next == NULL) { close(fd); throw; @@ -202,10 +202,10 @@ evio_service_accept_cb(ev_loop * /* loop */, ev_io *watcher, */ service->on_accept(service, fd, &addr); - } catch (const Exception& e) { + } catch (Exception *e) { if (fd >= 0) close(fd); - e.log(); + e->log(); } } @@ -237,7 +237,7 @@ evio_service_bind_and_listen(struct evio_service *service) if (service->on_bind) service->on_bind(service->on_bind_param); - } catch (const Exception& e) { + } catch (Exception *e) { close(fd); throw; } diff --git a/src/exception.cc b/src/exception.cc index de73973914..d048633690 100644 --- a/src/exception.cc +++ b/src/exception.cc @@ -28,11 +28,47 @@ */ #include "exception.h" #include "say.h" +#include "fiber.h" #include <stdio.h> #include <string.h> #include <errno.h> +/* Statically allocate out-of-memory exception */ +static ClientError out_of_memory(__FILE__, __LINE__, ER_MEMORY_ISSUE, 0, + "exception", "new"); + +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; + } + + return cord()->exc; +} + +void +Exception::operator delete(void*) +{ + /* Free memory allocated for exception */ + free(cord()->exc); + cord()->exc = NULL; + cord()->exc_size = 0; +} + Exception::Exception(const char *file, unsigned line) : m_file(file), m_line(line) { diff --git a/src/exception.h b/src/exception.h index 3829d16cb5..e46e611187 100644 --- a/src/exception.h +++ b/src/exception.h @@ -35,6 +35,9 @@ class Exception: public Object { public: + void *operator new(size_t size); + void operator delete(void*); + const char * errmsg() const { @@ -125,7 +128,7 @@ class ErrorInjection: public LoggedError { #define tnt_raise(...) tnt_raise0(__VA_ARGS__) #define tnt_raise0(class, ...) do { \ say_debug("%s at %s:%i", #class, __FILE__, __LINE__); \ - throw class(__FILE__, __LINE__, ##__VA_ARGS__); \ + throw new class(__FILE__, __LINE__, ##__VA_ARGS__); \ } while (0) #endif /* TARANTOOL_EXCEPTION_H_INCLUDED */ diff --git a/src/fiber.cc b/src/fiber.cc index 46c157cd76..63fd8ccdb3 100644 --- a/src/fiber.cc +++ b/src/fiber.cc @@ -377,12 +377,12 @@ fiber_loop(void *data __attribute__((unused))) fiber()->fid != 0); try { fiber()->f(fiber()->f_data); - } catch (const FiberCancelException& e) { + } catch (FiberCancelException *e) { say_info("fiber `%s' has been cancelled", fiber_name(fiber())); say_info("fiber `%s': exiting", fiber_name(fiber())); - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); } catch (...) { /* * This can only happen in case of a bug @@ -526,6 +526,9 @@ 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; } struct cord_thread_arg diff --git a/src/fiber.h b/src/fiber.h index 06d3b62ff4..e1a10de3b1 100644 --- a/src/fiber.h +++ b/src/fiber.h @@ -111,6 +111,7 @@ struct fiber { }; enum { FIBER_CALL_STACK = 16 }; +struct Exception; /** * @brief An independent execution unit that can be managed by a separate OS @@ -151,6 +152,9 @@ struct cord { /** A runtime slab cache for general use in this cord. */ struct slab_cache slabc; char name[FIBER_NAME_MAX]; + /** Last thrown exception */ + struct Exception *exc; + size_t exc_size; }; extern __thread struct cord *cord_ptr; diff --git a/src/iproto.cc b/src/iproto.cc index ebcd483aca..cad3173ab5 100644 --- a/src/iproto.cc +++ b/src/iproto.cc @@ -555,8 +555,8 @@ iproto_connection_on_input(ev_loop *loop, struct ev_io *watcher, */ if (!ev_is_active(&con->input)) ev_feed_event(loop, &con->input, EV_READ); - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); iproto_connection_shutdown(con); } } @@ -593,7 +593,7 @@ iproto_flush(struct iobuf *iobuf, int fd, struct obuf_svp *svp) nwr = sio_writev(fd, iov, iovcnt); sio_add_to_iov(iov, svp->iov_len); - } catch (const Exception &) { + } catch (Exception *e) { sio_add_to_iov(iov, svp->iov_len); throw; } @@ -630,8 +630,8 @@ iproto_connection_on_output(ev_loop *loop, struct ev_io *watcher, } if (ev_is_active(&con->output)) ev_io_stop(loop, &con->output); - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); iproto_connection_shutdown(con); } } @@ -691,7 +691,7 @@ iproto_process_request(struct iproto_request *ireq) request_create(&request, ireq->code); request_decode(&request, ireq->body, ireq->len); (*con->handler)((struct port *) &port, &request); - } catch (const ClientError &e) { + } catch (ClientError *e) { if (port.found) obuf_rollback_to_svp(out, &port.svp); iproto_reply_error(out, e, ireq->sync); @@ -711,17 +711,17 @@ iproto_process_connect(struct iproto_request *request) int fd = con->input.fd; try { /* connect. */ con->session = session_create(fd, con->cookie); - } catch (const ClientError& e) { + } catch (ClientError *e) { iproto_reply_error(&iobuf->out, e, request->sync); try { iproto_flush(iobuf, fd, &con->write_pos); - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); } iproto_connection_shutdown(con); return; - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); assert(con->session == NULL); iproto_connection_shutdown(con); return; diff --git a/src/iproto_port.cc b/src/iproto_port.cc index f76efb0a5b..2822aff42c 100644 --- a/src/iproto_port.cc +++ b/src/iproto_port.cc @@ -71,24 +71,23 @@ iproto_reply_ping(struct obuf *out, uint32_t sync) } void -iproto_reply_error(struct obuf *out, const ClientError &e, - uint32_t sync) +iproto_reply_error(struct obuf *out, ClientError *e, uint32_t sync) { - uint32_t msg_len = strlen(e.errmsg()); + uint32_t msg_len = strlen(e->errmsg()); struct iproto_header_bin header = iproto_header_bin; struct iproto_body_bin body = iproto_error_bin; uint32_t len = sizeof(header) - 5 + sizeof(body) + msg_len; header.v_len = mp_bswap_u32(len); - header.v_code = mp_bswap_u32(tnt_errcode_val(e.errcode())); + header.v_code = mp_bswap_u32(tnt_errcode_val(e->errcode())); header.v_sync = mp_bswap_u32(sync); body.v_data_len = mp_bswap_u32(msg_len); obuf_dup(out, &header, sizeof(header)); obuf_dup(out, &body, sizeof(body)); - obuf_dup(out, e.errmsg(), msg_len); + obuf_dup(out, e->errmsg(), msg_len); } static inline struct iproto_port * diff --git a/src/iproto_port.h b/src/iproto_port.h index 93d8fc2307..6ebb9ebf74 100644 --- a/src/iproto_port.h +++ b/src/iproto_port.h @@ -84,7 +84,7 @@ iproto_reply_ping(struct obuf *out, uint32_t sync); /** Send an error packet back. */ void -iproto_reply_error(struct obuf *out, const ClientError &e, +iproto_reply_error(struct obuf *out, ClientError *e, uint32_t sync); #endif /* TARANTOOL_IPROTO_PORT_H_INCLUDED */ diff --git a/src/lua/fiber.cc b/src/lua/fiber.cc index ffe2acd754..73f1ca7e79 100644 --- a/src/lua/fiber.cc +++ b/src/lua/fiber.cc @@ -406,7 +406,7 @@ box_lua_fiber_run(va_list ap __attribute__((unused))) lua_pushboolean(L, true); /* move 'true' to stack start */ lua_insert(L, 1); - } catch (const FiberCancelException &e) { + } catch (FiberCancelException *e) { if (box_lua_fiber_get_coro(L, fiber())) { struct fiber *caller = box_lua_fiber_get_caller(L); fiber_wakeup(caller); @@ -420,16 +420,16 @@ box_lua_fiber_run(va_list ap __attribute__((unused))) */ throw; - } catch (const Exception &e) { + } catch (Exception *e) { /* pop any possible garbage */ lua_settop(L, 0); /* completion status */ lua_pushboolean(L, false); /* error message */ - lua_pushstring(L, e.errmsg()); + lua_pushstring(L, e->errmsg()); /* Always log the error. */ - e.log(); + e->log(); } /* * L stack contains nothing but call results. @@ -551,10 +551,10 @@ box_lua_fiber_run_detached(va_list ap) struct lua_State *L = va_arg(ap, struct lua_State *); try { lbox_call(L, lua_gettop(L) - 1, LUA_MULTRET); - } catch (const FiberCancelException &e) { + } catch (FiberCancelException *e) { throw; - } catch (const Exception &e) { - e.log(); + } catch (Exception *e) { + e->log(); } } diff --git a/src/lua/init.cc b/src/lua/init.cc index 1fa60ef6fc..025ae5745b 100644 --- a/src/lua/init.cc +++ b/src/lua/init.cc @@ -197,7 +197,7 @@ lbox_pcall(struct lua_State *L) lua_pushboolean(L, true); /* move 'true' to stack start */ lua_insert(L, 1); - } catch (const ClientError& e) { + } catch (ClientError *e) { /* * Note: FiberCancelException passes through this * catch and thus leaves garbage on coroutine @@ -208,7 +208,7 @@ lbox_pcall(struct lua_State *L) /* completion status */ lua_pushboolean(L, false); /* error message */ - lua_pushstring(L, e.errmsg()); + lua_pushstring(L, e->errmsg()); } return lua_gettop(L); } @@ -359,11 +359,11 @@ tarantool_lua_dostring(struct lua_State *L, const char *str) } try { lbox_call(L, 0, LUA_MULTRET); - } catch (const FiberCancelException& e) { + } catch (FiberCancelException *e) { throw; - } catch (const Exception& e) { + } catch (Exception *e) { lua_settop(L, 0); - lua_pushstring(L, e.errmsg()); + lua_pushstring(L, e->errmsg()); return 1; } return 0; diff --git a/src/lua/socket.cc b/src/lua/socket.cc index 88ef6cf3fb..a586cae900 100644 --- a/src/lua/socket.cc +++ b/src/lua/socket.cc @@ -332,7 +332,7 @@ lbox_socket_connect(struct lua_State *L) /* set coio reader socket */ s->io_r.fd = s->io_w.fd; - } catch (const SocketError& e) { + } catch (SocketError *e) { freeaddrinfo(ai); return bio_pushsockerror(L, s, errno); } @@ -389,12 +389,12 @@ lbox_socket_send(struct lua_State *L) } mutex_unlock(&s->io_w_mutex); - } catch (const SocketError& e) { + } catch (SocketError *e) { mutex_unlock(&s->io_w_mutex); rc = bio_pushsenderror(L, s, 0, errno); return rc; - } catch (const Exception& e) { + } catch (Exception *e) { mutex_unlock(&s->io_w_mutex); throw; } @@ -457,12 +457,12 @@ lbox_socket_recv(struct lua_State *L) nrd = coio_bread_timeout(&s->io_r, in, to_read, delay); mutex_unlock(&s->io_r_mutex); - } catch (const SocketError& e) { + } catch (SocketError *e) { mutex_unlock(&s->io_r_mutex); rc = bio_pushrecverror(L, s, errno); return rc; - } catch (const Exception& e) { + } catch (Exception *e) { mutex_unlock(&s->io_r_mutex); throw; } @@ -694,11 +694,11 @@ lbox_socket_readline(struct lua_State *L) } mutex_unlock(&s->io_r_mutex); - } catch (const SocketError& e) { + } catch (SocketError *e) { mutex_unlock(&s->io_r_mutex); rc = bio_pushrecverror(L, s, errno); return rc; - } catch (const Exception& e) { + } catch (Exception *e) { mutex_unlock(&s->io_r_mutex); throw; } @@ -739,7 +739,7 @@ lbox_socket_bind(struct lua_State *L) try { evio_bind_addrinfo(&s->io_w, ai); freeaddrinfo(ai); - } catch (const SocketError& e) { + } catch (SocketError *e) { /* case #2: error */ freeaddrinfo(ai); return bio_pusherror(L, s, errno); @@ -797,7 +797,7 @@ lbox_socket_accept(struct lua_State *L) client->io_w.fd = coio_accept(&s->io_w, (struct sockaddr_in*)&addr, sizeof(addr), timeout); client->io_r.fd = client->io_w.fd; - } catch (const SocketError& e) { + } catch (SocketError *e) { return bio_pusherror(L, s, errno); } /* get user host and port */ @@ -870,7 +870,7 @@ lbox_socket_sendto(struct lua_State *L) if (a) { freeaddrinfo(a); } - } catch (const SocketError& e) { + } catch (SocketError *e) { /* case #2-3: error or timeout */ if (a) { freeaddrinfo(a); @@ -918,7 +918,7 @@ lbox_socket_recvfrom(struct lua_State *L) nrd = coio_recvfrom_timeout(&s->io_w, in->pos, buf_size, 0, (struct sockaddr_in*)&addr, sizeof(addr), timeout); - } catch (const SocketError& e) { + } catch (SocketError *e) { return bio_pushrecverror(L, s, errno); } if (nrd == 0) { diff --git a/src/lua/utils.h b/src/lua/utils.h index e481e5bf10..656083abc2 100644 --- a/src/lua/utils.h +++ b/src/lua/utils.h @@ -184,7 +184,7 @@ lbox_call(struct lua_State *L, int nargs, int nreturns) { try { lua_call(L, nargs, nreturns); - } catch (const Exception &e) { + } catch (Exception *e) { /* Let all well-behaved exceptions pass through. */ throw; } catch (...) { diff --git a/src/recovery.cc b/src/recovery.cc index d70674a940..80d1d22217 100644 --- a/src/recovery.cc +++ b/src/recovery.cc @@ -176,7 +176,7 @@ recovery_wait_lsn(struct recovery_state *r, int64_t lsn) try { fiber_yield(); wait_lsn_clear(&r->wait_lsn); - } catch (const Exception& e) { + } catch (Exception *e) { wait_lsn_clear(&r->wait_lsn); throw; } diff --git a/src/replica.cc b/src/replica.cc index a6946641ea..aeaa75d09d 100644 --- a/src/replica.cc +++ b/src/replica.cc @@ -132,14 +132,14 @@ pull_from_remote(va_list ap) iobuf_gc(iobuf); fiber_gc(); - } catch (const FiberCancelException& e) { + } catch (FiberCancelException *e) { title("replica", "%s/%s", r->remote->source, "failed"); iobuf_delete(iobuf); evio_close(loop, &coio); throw; - } catch (const Exception& e) { + } catch (Exception *e) { title("replica", "%s/%s", r->remote->source, "failed"); - e.log(); + e->log(); if (! warning_said) { if (err != NULL) say_info("%s", err); @@ -195,7 +195,7 @@ recovery_follow_remote(struct recovery_state *r, const char *addr) try { f = fiber_new(name, pull_from_remote); - } catch (const Exception& ) { + } catch (Exception *e) { return; } diff --git a/src/session.cc b/src/session.cc index a2dc0d4337..624439d6fb 100644 --- a/src/session.cc +++ b/src/session.cc @@ -74,7 +74,7 @@ session_create(int fd, uint64_t cookie) fiber_set_session(fiber(), session); try { trigger_run(&session_on_connect, NULL); - } catch (const Exception& e) { + } catch (Exception *e) { fiber_set_session(fiber(), NULL); mh_i32ptr_remove(session_registry, &node, NULL); mempool_free(&session_pool, session); @@ -92,8 +92,8 @@ session_destroy(struct session *session) try { trigger_run(&session_on_disconnect, NULL); - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); } catch (...) { /* catch all. */ } diff --git a/src/tarantool.cc b/src/tarantool.cc index cc5e942a32..c71d94aa9f 100644 --- a/src/tarantool.cc +++ b/src/tarantool.cc @@ -815,10 +815,11 @@ main(int argc, char **argv) signal_start(); ev_run(loop(), 0); } - } catch (const Exception& e) { - e.log(); + } catch (Exception *e) { + e->log(); panic("%s", "fatal error, exiting the event loop"); } + if (start_loop) say_crit("exiting the event loop"); /* freeing resources */ diff --git a/test/box/misc.result b/test/box/misc.result index 9488a70b35..726b8a3f65 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -59,6 +59,12 @@ t = nil ---------------- -- # box.raise ---------------- +--# stop server default +--# start server default +-- do nothing - no exceptions were thrown before +box.raise() +--- +... 1 + 1 --- - 2 @@ -75,6 +81,17 @@ box.raise(12, 345) --- - error: '345' ... +box.raise() +--- +- error: '345' +... +box.raise() +--- +- error: '345' +... +space = box.space.tweedledum +--- +... ---------------- -- # box.stat ---------------- diff --git a/test/box/misc.test.lua b/test/box/misc.test.lua index dd96ea4866..417761580c 100644 --- a/test/box/misc.test.lua +++ b/test/box/misc.test.lua @@ -12,10 +12,20 @@ t = nil ---------------- -- # box.raise ---------------- + +--# stop server default +--# start server default +-- do nothing - no exceptions were thrown before +box.raise() + 1 + 1 box.raise(123, 'test') box.raise(0, 'the other test') box.raise(12, 345) +box.raise() +box.raise() + +space = box.space.tweedledum ---------------- -- # box.stat -- GitLab