From a8dcee6fef5a89512916e7f9d734fd224f8d71ac Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Thu, 25 Dec 2014 17:58:38 +0300
Subject: [PATCH] Rename libcore to libserver.

libcore is a thick a thick bundle with almost everything.
Rename it to libserver.

Extract the minimal server core with fibers & exceptions into libcore.

Add a prototype unit test for fibers.
---
 src/CMakeLists.txt       | 41 ++++++++++---------
 src/box/CMakeLists.txt   |  2 +
 src/box/bitset_index.cc  |  1 -
 src/box/cluster.cc       |  1 -
 src/box/engine.cc        |  1 -
 src/box/engine.h         |  1 -
 src/box/engine_memtx.cc  |  1 -
 src/box/engine_sophia.cc |  1 -
 src/{ => box}/errcode.c  |  1 +
 src/{ => box}/errcode.h  | 16 +++++---
 src/box/error.cc         | 75 +++++++++++++++++++++++++++++++++++
 src/box/error.h          | 85 ++++++++++++++++++++++++++++++++++++++++
 src/box/hash_index.cc    |  1 -
 src/box/index.cc         |  1 -
 src/box/index.h          |  1 -
 src/box/iproto.cc        | 18 ++++-----
 src/box/iproto_port.cc   | 14 ++++++-
 src/box/iproto_port.h    |  2 +-
 src/box/key_def.cc       |  1 -
 src/box/key_def.h        |  2 +-
 src/box/lua/error.cc     |  2 +-
 src/box/replication.cc   |  1 +
 src/box/rtree_index.cc   |  1 -
 src/box/schema.h         |  3 +-
 src/box/session.cc       |  1 -
 src/box/sophia_index.cc  |  1 -
 src/box/space.cc         |  1 -
 src/box/space.h          |  1 -
 src/box/tree_index.cc    |  1 -
 src/box/tuple.cc         |  1 -
 src/box/tuple_update.cc  |  2 +-
 src/box/vclock.h         |  2 +-
 src/box/xrow.cc          |  1 -
 src/coeio.cc             | 24 ++++++++++++
 src/coeio.h              | 13 ++++++
 src/coio.cc              |  3 +-
 src/coro.cc              |  3 +-
 src/evio.cc              |  2 +-
 src/exception.cc         | 61 +++++++++++-----------------
 src/exception.h          | 63 +++++------------------------
 src/fiber.cc             | 35 ++---------------
 src/fiber.h              | 15 ++-----
 src/iobuf.cc             |  3 +-
 src/lib/small/mempool.h  |  6 +--
 src/lib/small/region.h   |  3 +-
 src/lib/small/small.h    |  3 +-
 src/lua/fiber.cc         |  5 ++-
 src/lua/init.cc          |  2 +-
 src/lua/trigger.cc       |  2 +-
 src/lua/utils.cc         |  8 ++++
 src/lua/utils.h          | 14 ++++---
 src/pickle.h             | 29 --------------
 test/box/session.result  |  4 +-
 test/unit/CMakeLists.txt | 10 +++--
 test/unit/fiber.cc       | 10 +++++
 test/unit/fiber.result   |  0
 56 files changed, 350 insertions(+), 252 deletions(-)
 rename src/{ => box}/errcode.c (98%)
 rename src/{ => box}/errcode.h (97%)
 create mode 100644 src/box/error.cc
 create mode 100644 src/box/error.h
 create mode 100644 test/unit/fiber.cc
 create mode 100644 test/unit/fiber.result

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f0028d08b1..18784fd0ba 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -42,9 +42,25 @@ add_custom_target(ragel
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
     COMMAND ragel -G2 src/uri.rl -o src/uri.c)
 
-set (common_sources
+set (core_sources
+     say.cc
      memory.cc
      fiber.cc
+     exception.cc
+     coro.cc
+     object.cc
+     assoc.c
+ )
+
+add_library(core STATIC ${core_sources})
+target_link_libraries(core
+    salad small
+    ${LIBEV_LIBRARIES}
+    ${LIBEIO_LIBRARIES}
+    ${LIBCORO_LIBRARIES}
+)
+
+set (server_sources
      util.cc
      find_path.c
      sio.cc
@@ -54,15 +70,9 @@ set (common_sources
      iobuf.cc
      coio_buf.cc
      pickle.cc
-     coro.cc
      stat.cc
-     object.cc
-     exception.cc
      ipc.cc
      errinj.cc
-     errcode.c
-     assoc.c
-     say.cc
      fio.c
      crc32.c
      random.c
@@ -90,19 +100,16 @@ set (common_sources
 )
 
 if (ENABLE_TRACE)
-    set (common_sources ${common_sources} trace.c)
+    set (server_sources ${server_sources} trace.c)
 endif()
 
-set_source_files_compile_flags(${common_sources})
-add_library(core STATIC ${common_sources})
-target_link_libraries(core pthread)
+set_source_files_compile_flags(${server_sources})
+add_library(server STATIC ${server_sources})
+target_link_libraries(server core pthread)
 
-set (common_libraries core small salad misc bitset msgpuck)
+set (common_libraries server core misc bitset msgpuck)
 
 list(APPEND common_libraries
-    ${LIBEV_LIBRARIES}
-    ${LIBEIO_LIBRARIES}
-    ${LIBCORO_LIBRARIES}
     ${LIBGOPT_LIBRARIES}
     ${LIBCJSON_LIBRARIES}
     ${LIBYAML_LIBRARIES}
@@ -110,10 +117,6 @@ list(APPEND common_libraries
     ${LUAJIT_LIB}
 )
 
-set (THREAD_LIB pthread)
-
-set (common_libraries ${common_libraries} ${THREAD_LIB})
-
 if (TARGET_OS_LINUX OR TARGET_OS_DEBIAN_FREEBSD)
     set (common_libraries ${common_libraries} dl)
 endif()
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 764d85c154..7ec1dcf708 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -20,6 +20,8 @@ add_library(box
     iproto.cc
     iproto_constants.c
     iproto_port.cc
+    errcode.c
+    error.cc
     xrow.cc
     xlog.cc
     tuple.cc
diff --git a/src/box/bitset_index.cc b/src/box/bitset_index.cc
index 992af64cde..4b04adb8d5 100644
--- a/src/box/bitset_index.cc
+++ b/src/box/bitset_index.cc
@@ -32,7 +32,6 @@
 #include <string.h>
 
 #include "tuple.h"
-#include "exception.h"
 #include "bitset/index.h"
 
 static inline struct tuple *
diff --git a/src/box/cluster.cc b/src/box/cluster.cc
index 031ecff6a6..56490b4ce8 100644
--- a/src/box/cluster.cc
+++ b/src/box/cluster.cc
@@ -29,7 +29,6 @@
 #include "box.h"
 #include "cluster.h"
 #include "recovery.h"
-#include "exception.h"
 
 /**
  * Globally unique identifier of this cluster.
diff --git a/src/box/engine.cc b/src/box/engine.cc
index ffa5283039..13cb149224 100644
--- a/src/box/engine.cc
+++ b/src/box/engine.cc
@@ -28,7 +28,6 @@
  */
 #include "engine.h"
 #include "space.h"
-#include "exception.h"
 #include "salad/rlist.h"
 #include <stdlib.h>
 #include <string.h>
diff --git a/src/box/engine.h b/src/box/engine.h
index 478ea0e043..c811cef6d5 100644
--- a/src/box/engine.h
+++ b/src/box/engine.h
@@ -28,7 +28,6 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <exception.h>
 #include "index.h"
 
 struct space;
diff --git a/src/box/engine_memtx.cc b/src/box/engine_memtx.cc
index 2118b15d14..2011f03742 100644
--- a/src/box/engine_memtx.cc
+++ b/src/box/engine_memtx.cc
@@ -36,7 +36,6 @@
 #include "rtree_index.h"
 #include "bitset_index.h"
 #include "space.h"
-#include "exception.h"
 #include "salad/rlist.h"
 #include <stdlib.h>
 #include <string.h>
diff --git a/src/box/engine_sophia.cc b/src/box/engine_sophia.cc
index efccbb2a58..a8c158dfbc 100644
--- a/src/box/engine_sophia.cc
+++ b/src/box/engine_sophia.cc
@@ -36,7 +36,6 @@
 #include "index.h"
 #include "sophia_index.h"
 #include "space.h"
-#include "exception.h"
 #include "salad/rlist.h"
 #include <sophia.h>
 #include <stdlib.h>
diff --git a/src/errcode.c b/src/box/errcode.c
similarity index 98%
rename from src/errcode.c
rename to src/box/errcode.c
index 9cc3615e73..e90747e439 100644
--- a/src/errcode.c
+++ b/src/box/errcode.c
@@ -27,6 +27,7 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+#include "errcode.h"
 
 #define ERRCODE_RECORD_MEMBER(s, f, d) {	\
 	.errstr = #s,				\
diff --git a/src/errcode.h b/src/box/errcode.h
similarity index 97%
rename from src/errcode.h
rename to src/box/errcode.h
index a128fe3319..7d0f973c1a 100644
--- a/src/errcode.h
+++ b/src/box/errcode.h
@@ -1,5 +1,5 @@
-#ifndef TARANTOOL_ERRCODE_H_INCLUDED
-#define TARANTOOL_ERRCODE_H_INCLUDED
+#ifndef TARANTOOL_BOX_ERRCODE_H_INCLUDED
+#define TARANTOOL_BOX_ERRCODE_H_INCLUDED
 /*
  * Redistribution and use in source and binary forms, with or
  * without modification, are permitted provided that the following
@@ -32,14 +32,16 @@
 
 #include "trivia/util.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct errcode_record {
 	const char *errstr;
 	const char *errdesc;
 	uint8_t errflags;
 };
 
-enum { TNT_ERRMSG_MAX = 512 };
-
 /*
  * To add a new error code to Tarantool, extend this array.
  *
@@ -172,4 +174,8 @@ static inline const char *tnt_errcode_desc(uint32_t errcode)
 	return tnt_error_codes[errcode].errdesc;
 }
 
-#endif /* TARANTOOL_ERRCODE_H_INCLUDED */
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* TARANTOOL_BOX_ERRCODE_H_INCLUDED */
diff --git a/src/box/error.cc b/src/box/error.cc
new file mode 100644
index 0000000000..f3fc39e74e
--- /dev/null
+++ b/src/box/error.cc
@@ -0,0 +1,75 @@
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "error.h"
+#include <stdio.h>
+#include <typeinfo>
+
+ClientError::ClientError(const char *file, unsigned line, uint32_t errcode, ...)
+	: Exception(file, line)
+{
+	m_errcode = errcode;
+	va_list ap;
+	va_start(ap, errcode);
+	vsnprintf(m_errmsg, sizeof(m_errmsg) - 1,
+		  tnt_errcode_desc(m_errcode), ap);
+	m_errmsg[sizeof(m_errmsg) - 1] = 0;
+	va_end(ap);
+}
+
+ClientError::ClientError(const char *file, unsigned line, const char *msg,
+			 uint32_t errcode)
+	: Exception(file, line)
+{
+	m_errcode = errcode;
+	strncpy(m_errmsg, msg, sizeof(m_errmsg) - 1);
+	m_errmsg[sizeof(m_errmsg) - 1] = 0;
+}
+
+void
+ClientError::log() const
+{
+	_say(S_ERROR, m_file, m_line, NULL, "%s: %s", tnt_errcode_str(m_errcode),
+	     m_errmsg);
+}
+
+
+uint32_t
+ClientError::get_code_for_foreign_exception(const Exception *e)
+{
+	if (typeid(*e) == typeid(OutOfMemory))
+		return ER_MEMORY_ISSUE;
+	return ER_PROC_LUA;
+}
+
+ErrorInjection::ErrorInjection(const char *file, unsigned line, const char *msg)
+	: LoggedError(file, line, ER_INJECTION, msg)
+{
+	/* nothing */
+}
+
diff --git a/src/box/error.h b/src/box/error.h
new file mode 100644
index 0000000000..908e46c320
--- /dev/null
+++ b/src/box/error.h
@@ -0,0 +1,85 @@
+#ifndef TARANTOOL_BOX_ERROR_H_INCLUDED
+#define TARANTOOL_BOX_ERROR_H_INCLUDED
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "errcode.h"
+#include "exception.h"
+
+class ClientError: public Exception {
+public:
+	virtual void raise()
+	{
+		throw this;
+	}
+
+	virtual void log() const;
+
+	int
+	errcode() const
+	{
+		return m_errcode;
+	}
+
+	ClientError(const char *file, unsigned line, uint32_t errcode, ...);
+	/* A special constructor for lbox_raise */
+	ClientError(const char *file, unsigned line, const char *msg,
+		    uint32_t errcode);
+
+	static uint32_t get_code_for_foreign_exception(const Exception *e);
+private:
+	/* client errno code */
+	int m_errcode;
+};
+
+class LoggedError: public ClientError {
+public:
+	template <typename ... Args>
+	LoggedError(const char *file, unsigned line, uint32_t errcode, Args ... args)
+		: ClientError(file, line, errcode, args...)
+	{
+		/* TODO: actually calls ClientError::log */
+		log();
+	}
+};
+
+class IllegalParams: public LoggedError {
+public:
+	template <typename ... Args>
+	IllegalParams(const char *file, unsigned line, const char *format,
+		      Args ... args)
+		:LoggedError(file, line, ER_ILLEGAL_PARAMS,
+			     format, args...) {}
+};
+
+class ErrorInjection: public LoggedError {
+public:
+	ErrorInjection(const char *file, unsigned line, const char *msg);
+};
+
+#endif /* TARANTOOL_BOX_ERROR_H_INCLUDED */
diff --git a/src/box/hash_index.cc b/src/box/hash_index.cc
index 75b60d2bc4..3591a3ff43 100644
--- a/src/box/hash_index.cc
+++ b/src/box/hash_index.cc
@@ -29,7 +29,6 @@
 #include "hash_index.h"
 #include "say.h"
 #include "tuple.h"
-#include "exception.h"
 #include "errinj.h"
 
 #include "third_party/PMurHash.h"
diff --git a/src/box/index.cc b/src/box/index.cc
index 209d92aa73..c577549b8e 100644
--- a/src/box/index.cc
+++ b/src/box/index.cc
@@ -33,7 +33,6 @@
 #include "sophia_index.h"
 #include "tuple.h"
 #include "say.h"
-#include "exception.h"
 #include "schema.h"
 
 STRS(iterator_type, ITERATOR_TYPE);
diff --git a/src/box/index.h b/src/box/index.h
index a86fd2f1c7..7b609c3a05 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -33,7 +33,6 @@
 
 #include "object.h"
 #include "key_def.h"
-#include "exception.h"
 
 struct tuple;
 
diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index b7a371d67c..c2b04236d9 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -34,8 +34,6 @@
 
 #include "iproto_port.h"
 #include "tarantool.h"
-#include "exception.h"
-#include "errcode.h"
 #include "fiber.h"
 #include "say.h"
 #include "evio.h"
@@ -584,7 +582,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 (Exception *) {
+	} catch (SocketError *) {
 		sio_add_to_iov(iov, svp->iov_len);
 		throw;
 	}
@@ -660,7 +658,7 @@ iproto_process_dml(struct iproto_request *ireq)
 	iproto_port_init(&port, out, ireq->header.sync);
 	try {
 		box_process((struct port *) &port, &ireq->request);
-	} catch (ClientError *e) {
+	} catch (Exception *e) {
 		if (port.found)
 			obuf_rollback_to_svp(out, &port.svp);
 		iproto_reply_error(out, e, ireq->header.sync);
@@ -714,7 +712,7 @@ iproto_process_admin(struct iproto_request *ireq)
 			tnt_raise(ClientError, ER_UNKNOWN_REQUEST_TYPE,
 				   (uint32_t) ireq->header.type);
 		}
-	} catch (ClientError *e) {
+	} catch (Exception *e) {
 		say_error("admin command error: %s", e->errmsg());
 		iproto_reply_error(&iobuf->out, e, ireq->header.sync);
 	}
@@ -763,7 +761,11 @@ iproto_process_connect(struct iproto_request *request)
 			   IPROTO_GREETING_SIZE);
 		if (! rlist_empty(&session_on_connect))
 			session_run_on_connect_triggers(con->session);
-	} catch (ClientError *e) {
+	} catch (SocketError *e) {
+		e->log();
+		iproto_connection_close(con);
+		return;
+	} catch (Exception *e) {
 		iproto_reply_error(&iobuf->out, e, request->header.type);
 		try {
 			iproto_flush(iobuf, fd, &con->write_pos);
@@ -772,10 +774,6 @@ iproto_process_connect(struct iproto_request *request)
 		}
 		iproto_connection_close(con);
 		return;
-	} catch (Exception *e) {
-		e->log();
-		iproto_connection_close(con);
-		return;
 	}
 	/*
 	 * Connect is synchronous, so no one could have been
diff --git a/src/box/iproto_port.cc b/src/box/iproto_port.cc
index b1f227dd1d..d2810a08b5 100644
--- a/src/box/iproto_port.cc
+++ b/src/box/iproto_port.cc
@@ -77,17 +77,27 @@ iproto_reply_ping(struct obuf *out, uint64_t sync)
 	obuf_dup(out, &reply, sizeof(reply));
 }
 
+static inline uint32_t
+get_errcode(const Exception *e)
+{
+	const ClientError *error = dynamic_cast<const ClientError *>(e);
+	if (error)
+		return error->errcode();
+	return ClientError::get_code_for_foreign_exception(e);
+}
+
 void
-iproto_reply_error(struct obuf *out, const ClientError *e, uint64_t sync)
+iproto_reply_error(struct obuf *out, const Exception *e, uint64_t sync)
 {
 	uint32_t msg_len = strlen(e->errmsg());
+	uint32_t errcode = get_errcode(e);
 
 	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(iproto_encode_error(e->errcode()));
+	header.v_code = mp_bswap_u32(iproto_encode_error(errcode));
 	header.v_sync = mp_bswap_u64(sync);
 
 	body.v_data_len = mp_bswap_u32(msg_len);
diff --git a/src/box/iproto_port.h b/src/box/iproto_port.h
index 0613854abf..9349f71c60 100644
--- a/src/box/iproto_port.h
+++ b/src/box/iproto_port.h
@@ -86,6 +86,6 @@ iproto_reply_ping(struct obuf *out, uint64_t sync);
 
 /** Send an error packet back. */
 void
-iproto_reply_error(struct obuf *out, const ClientError *e, uint64_t sync);
+iproto_reply_error(struct obuf *out, const Exception *e, uint64_t sync);
 
 #endif /* TARANTOOL_IPROTO_PORT_H_INCLUDED */
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index 7a071d490e..54b655dccb 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -31,7 +31,6 @@
 #include "schema.h"
 #include <stdlib.h>
 #include <stdio.h>
-#include "exception.h"
 
 const char *field_type_strs[] = {"UNKNOWN", "NUM", "STR", "ARRAY", "NUMBER", ""};
 STRS(index_type, ENUM_INDEX_TYPE);
diff --git a/src/box/key_def.h b/src/box/key_def.h
index b347740c54..574b2651c0 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -30,7 +30,7 @@
  */
 #include "trivia/util.h"
 #include "salad/rlist.h"
-#include <exception.h>
+#include "error.h"
 #include "msgpuck/msgpuck.h"
 #define RB_COMPACT 1
 #include "third_party/rb.h"
diff --git a/src/box/lua/error.cc b/src/box/lua/error.cc
index 00d3baabef..6c817a6f38 100644
--- a/src/box/lua/error.cc
+++ b/src/box/lua/error.cc
@@ -35,10 +35,10 @@ extern "C" {
 } /* extern "C" */
 
 #include <fiber.h>
-#include <errcode.h>
 #include <errinj.h>
 
 #include "lua/utils.h"
+#include "box/error.h"
 
 static int
 lbox_raise(lua_State *L)
diff --git a/src/box/replication.cc b/src/box/replication.cc
index ab7bbaa299..dd54ab0167 100644
--- a/src/box/replication.cc
+++ b/src/box/replication.cc
@@ -51,6 +51,7 @@
 #include "box/vclock.h"
 #include "scoped_guard.h"
 #include "xrow.h"
+#include "coeio.h"
 
 /** Replication topology
  * ----------------------
diff --git a/src/box/rtree_index.cc b/src/box/rtree_index.cc
index 5869d24d00..a54ec9ffc2 100644
--- a/src/box/rtree_index.cc
+++ b/src/box/rtree_index.cc
@@ -29,7 +29,6 @@
 #include "rtree_index.h"
 #include "tuple.h"
 #include "space.h"
-#include "exception.h"
 #include "errinj.h"
 #include "fiber.h"
 #include "small/small.h"
diff --git a/src/box/schema.h b/src/box/schema.h
index cbd77926c2..201293ec78 100644
--- a/src/box/schema.h
+++ b/src/box/schema.h
@@ -28,7 +28,7 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include "exception.h"
+#include "error.h"
 #include <stdio.h> /* snprintf */
 
 enum schema_id {
@@ -163,5 +163,4 @@ func_by_name(const char *name, uint32_t name_len)
 bool
 schema_find_grants(const char *type, uint32_t id);
 
-
 #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */
diff --git a/src/box/session.cc b/src/box/session.cc
index 28df060602..b0f9519760 100644
--- a/src/box/session.cc
+++ b/src/box/session.cc
@@ -32,7 +32,6 @@
 
 #include "assoc.h"
 #include "trigger.h"
-#include "exception.h"
 #include "random.h"
 #include <sys/socket.h>
 #include "user.h"
diff --git a/src/box/sophia_index.cc b/src/box/sophia_index.cc
index ebe9abb726..8191090c1f 100644
--- a/src/box/sophia_index.cc
+++ b/src/box/sophia_index.cc
@@ -30,7 +30,6 @@
 #include "say.h"
 #include "tuple.h"
 #include "scoped_guard.h"
-#include "exception.h"
 #include "errinj.h"
 #include "schema.h"
 #include "space.h"
diff --git a/src/box/space.cc b/src/box/space.cc
index 8350b8cdd4..413bfc03c4 100644
--- a/src/box/space.cc
+++ b/src/box/space.cc
@@ -29,7 +29,6 @@
 #include "space.h"
 #include <stdlib.h>
 #include <string.h>
-#include <exception.h>
 #include "tuple.h"
 #include "scoped_guard.h"
 #include "trigger.h"
diff --git a/src/box/space.h b/src/box/space.h
index f171e68ca8..d6168e611d 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -32,7 +32,6 @@
 #include "key_def.h"
 #include "engine.h"
 #include "salad/rlist.h"
-#include <exception.h>
 
 struct space {
 	struct access access[BOX_USER_MAX];
diff --git a/src/box/tree_index.cc b/src/box/tree_index.cc
index d877a09e46..122e068bba 100644
--- a/src/box/tree_index.cc
+++ b/src/box/tree_index.cc
@@ -29,7 +29,6 @@
 #include "tree_index.h"
 #include "tuple.h"
 #include "space.h"
-#include "exception.h"
 #include "errinj.h"
 #include "memory.h"
 #include "fiber.h"
diff --git a/src/box/tuple.cc b/src/box/tuple.cc
index d00728e2c8..0791038dbc 100644
--- a/src/box/tuple.cc
+++ b/src/box/tuple.cc
@@ -33,7 +33,6 @@
 
 #include "key_def.h"
 #include "tuple_update.h"
-#include <exception.h>
 #include <stdio.h>
 
 /** Global table of tuple formats */
diff --git a/src/box/tuple_update.cc b/src/box/tuple_update.cc
index 6026259d2f..df68bb3bbd 100644
--- a/src/box/tuple_update.cc
+++ b/src/box/tuple_update.cc
@@ -33,7 +33,7 @@
 #include "third_party/queue.h"
 
 #include "salad/rope.h"
-#include <exception.h>
+#include "error.h"
 #include "msgpuck/msgpuck.h"
 
 /** UPDATE request implementation.
diff --git a/src/box/vclock.h b/src/box/vclock.h
index 4318b54bad..d438a7bdfd 100644
--- a/src/box/vclock.h
+++ b/src/box/vclock.h
@@ -192,7 +192,7 @@ vclockset_isearch(vclockset_t *set, struct vclock *key)
 #if defined(__cplusplus)
 } /* extern "C" */
 
-#include "exception.h"
+#include "error.h"
 
 /**
  * Allocate a new vclock object and initialize it
diff --git a/src/box/xrow.cc b/src/box/xrow.cc
index 1f5761d313..aedc8d19d3 100644
--- a/src/box/xrow.cc
+++ b/src/box/xrow.cc
@@ -28,7 +28,6 @@
  */
 #include "xrow.h"
 #include "msgpuck/msgpuck.h"
-#include "exception.h"
 #include "fiber.h"
 #include "tt_uuid.h"
 #include "vclock.h"
diff --git a/src/coeio.cc b/src/coeio.cc
index 9ff1293226..6ea8282244 100644
--- a/src/coeio.cc
+++ b/src/coeio.cc
@@ -283,3 +283,27 @@ coeio_resolve(int socktype, const char *host, const char *port,
 		return NULL;
 	return result;
 }
+
+ssize_t
+cord_cojoin_cb(va_list ap)
+{
+	struct cord *cord = va_arg(ap, struct cord *);
+	void *retval = NULL;
+	int res = tt_pthread_join(cord->id, &retval);
+	return res;
+}
+
+int
+cord_cojoin(struct cord *cord)
+{
+	assert(cord() != cord); /* Can't join self. */
+	int rc = coeio_custom(cord_cojoin_cb, TIMEOUT_INFINITY, cord);
+	if (rc == 0 && cord->exception) {
+		Exception::move(cord, cord());
+		cord_destroy(cord);
+		cord()->exception->raise(); /* re-throw exception from cord */
+	}
+	cord_destroy(cord);
+	return rc;
+}
+
diff --git a/src/coeio.h b/src/coeio.h
index 6536063c55..da7d18ce0d 100644
--- a/src/coeio.h
+++ b/src/coeio.h
@@ -67,4 +67,17 @@ coeio_resolve(int socktype, const char *host, const char *port,
 #if defined(__cplusplus)
 }
 #endif
+
+struct cord;
+/**
+ * \brief Yield until \a cord has terminated.
+ * If \a cord has terminated with an uncaught exception
+ * **re-throws** this exception in the calling cord/fiber.
+ * \param cord cord
+ * \sa pthread_join()
+ * \return 0 on success
+ */
+int
+cord_cojoin(struct cord *cord);
+
 #endif /* TARANTOOL_COEIO_H_INCLUDED */
diff --git a/src/coio.cc b/src/coio.cc
index b8b5e5edd2..e2903365f1 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -410,7 +410,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 (Exception *e) {
+	} catch (SocketError *e) {
 		sio_add_to_iov(iov, offset);
 		throw;
 	}
@@ -578,6 +578,7 @@ coio_service_on_accept(struct evio_service *evio_service,
 		iobuf = iobuf_new(iobuf_name);
 		f = fiber_new(fiber_name, service->handler);
 	} catch (Exception *e) {
+		e->log();
 		say_error("can't create a handler fiber, dropping client connection");
 		evio_close(loop(), &coio);
 		if (iobuf)
diff --git a/src/coro.cc b/src/coro.cc
index 74bdb283c9..eb3aebaafc 100644
--- a/src/coro.cc
+++ b/src/coro.cc
@@ -51,8 +51,7 @@ tarantool_coro_create(struct tarantool_coro *coro,
 					+ slab_sizeof();
 
 	if (coro->stack == NULL) {
-		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
-			  sizeof(coro->stack_size),
+		tnt_raise(OutOfMemory, sizeof(coro->stack_size),
 			  "mmap", "coro stack");
 	}
 
diff --git a/src/evio.cc b/src/evio.cc
index 7ce4e681b1..1d3cbead4a 100644
--- a/src/evio.cc
+++ b/src/evio.cc
@@ -297,7 +297,7 @@ evio_service_init(ev_loop *loop,
 
 	struct uri u;
 	if (uri_parse(&u, uri) || u.service == NULL)
-		tnt_raise(IllegalParams, "invalid uri for bind: %s", uri);
+		tnt_raise(SocketError, -1, "invalid uri for bind: %s", uri);
 
 	snprintf(service->serv, sizeof(service->serv), "%.*s",
 		 (int) u.service_len, u.service);
diff --git a/src/exception.cc b/src/exception.cc
index aefc9f26e5..a9e45e42c6 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -33,10 +33,10 @@
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
+#include <typeinfo>
 
-/* Statically allocate out-of-memory exception */
-ClientError out_of_memory(__FILE__, __LINE__, ER_MEMORY_ISSUE, 0,
-			  "exception", "new");
+static OutOfMemory out_of_memory(__FILE__, __LINE__,
+				 sizeof(OutOfMemory), "malloc", "exception");
 
 void *
 Exception::operator new(size_t size)
@@ -56,7 +56,7 @@ Exception::operator new(size_t size)
 		}
 		free(cord->exception);
 	}
-	cord->exception = (ClientError *) malloc(size);
+	cord->exception = (Exception *) malloc(size);
 	if (cord->exception) {
 		cord->exception_size = size;
 		return cord->exception;
@@ -112,9 +112,17 @@ Exception::Exception(const Exception& e)
 	memcpy(m_errmsg, e.m_errmsg, sizeof(m_errmsg));
 }
 
+void
+Exception::log() const
+{
+	_say(S_ERROR, m_file, m_line, "%s %s",
+	     typeid(*this).name(), m_errmsg);
+}
+
+
 SystemError::SystemError(const char *file, unsigned line)
 	: Exception(file, line),
-	  m_errnum(errno)
+	  m_errno(errno)
 {
 	/* nothing */
 }
@@ -137,42 +145,17 @@ SystemError::init(const char *format, va_list ap)
 void
 SystemError::log() const
 {
-	_say(S_SYSERROR, m_file, m_line, strerror(m_errnum), "SystemError %s",
+	_say(S_SYSERROR, m_file, m_line, strerror(m_errno), "SystemError %s",
 	     m_errmsg);
 }
 
-
-ClientError::ClientError(const char *file, unsigned line, uint32_t errcode, ...)
-	: Exception(file, line)
-{
-	m_errcode = errcode;
-	va_list ap;
-	va_start(ap, errcode);
-	vsnprintf(m_errmsg, sizeof(m_errmsg) - 1,
-		  tnt_errcode_desc(m_errcode), ap);
-	m_errmsg[sizeof(m_errmsg) - 1] = 0;
-	va_end(ap);
-}
-
-ClientError::ClientError(const char *file, unsigned line, const char *msg,
-			 uint32_t errcode)
-	: Exception(file, line)
+OutOfMemory::OutOfMemory(const char *file, unsigned line,
+			 size_t amount, const char *allocator,
+			 const char *object)
+	:SystemError(file, line)
 {
-	m_errcode = errcode;
-	strncpy(m_errmsg, msg, sizeof(m_errmsg) - 1);
-	m_errmsg[sizeof(m_errmsg) - 1] = 0;
+	m_errno = ENOMEM;
+	snprintf(m_errmsg, sizeof(m_errmsg),
+		 "Failed to allocate %u bytes in %s for %s",
+		 (unsigned) amount, allocator, object);
 }
-
-void
-ClientError::log() const
-{
-	_say(S_ERROR, m_file, m_line, NULL, "%s: %s", tnt_errcode_str(m_errcode),
-	     m_errmsg);
-}
-
-ErrorInjection::ErrorInjection(const char *file, unsigned line, const char *msg)
-	: LoggedError(file, line, ER_INJECTION, msg)
-{
-	/* nothing */
-}
-
diff --git a/src/exception.h b/src/exception.h
index d9afb096db..c241523a2a 100644
--- a/src/exception.h
+++ b/src/exception.h
@@ -30,11 +30,12 @@
  */
 #include "object.h"
 #include <stdarg.h>
-#include "errcode.h"
 #include "say.h"
 
 struct cord;
 
+enum { TNT_ERRMSG_MAX = 512 };
+
 class Exception: public Object {
 public:
 	void *operator new(size_t size);
@@ -51,7 +52,7 @@ class Exception: public Object {
 		return m_errmsg;
 	}
 
-	virtual void log() const = 0;
+	virtual void log() const;
 	virtual ~Exception() {}
 
 	static void init(struct cord *cord);
@@ -84,7 +85,7 @@ class SystemError: public Exception {
 	int
 	errnum() const
 	{
-		return m_errnum;
+		return m_errno;
 	}
 
 	virtual void log() const;
@@ -98,60 +99,16 @@ class SystemError: public Exception {
 	void
 	init(const char *format, va_list ap);
 
-private:
+protected:
 	/* system errno */
-	int m_errnum;
-};
-
-class ClientError: public Exception {
-public:
-	virtual void raise()
-	{
-		throw this;
-	}
-
-	virtual void log() const;
-
-	int
-	errcode() const
-	{
-		return m_errcode;
-	}
-
-	ClientError(const char *file, unsigned line, uint32_t errcode, ...);
-	/* A special constructor for lbox_raise */
-	ClientError(const char *file, unsigned line, const char *msg,
-		    uint32_t errcode);
-private:
-	/* client errno code */
-	int m_errcode;
-};
-
-extern ClientError out_of_memory;
-
-class LoggedError: public ClientError {
-public:
-	template <typename ... Args>
-	LoggedError(const char *file, unsigned line, uint32_t errcode, Args ... args)
-		: ClientError(file, line, errcode, args...)
-	{
-		/* TODO: actually calls ClientError::log */
-		log();
-	}
-};
-
-class IllegalParams: public LoggedError {
-public:
-	template <typename ... Args>
-	IllegalParams(const char *file, unsigned line, const char *format,
-		      Args ... args)
-		:LoggedError(file, line, ER_ILLEGAL_PARAMS,
-			     format, args...) {}
+	int m_errno;
 };
 
-class ErrorInjection: public LoggedError {
+class OutOfMemory: public SystemError {
 public:
-	ErrorInjection(const char *file, unsigned line, const char *msg);
+	OutOfMemory(const char *file, unsigned line,
+		    size_t amount, const char *allocator,
+		    const char *object);
 };
 
 #define tnt_raise(...) tnt_raise0(__VA_ARGS__)
diff --git a/src/fiber.cc b/src/fiber.cc
index b8b2dd07d8..b6f7109b53 100644
--- a/src/fiber.cc
+++ b/src/fiber.cc
@@ -33,11 +33,9 @@
 #include <string.h>
 
 #include "say.h"
-#include "stat.h"
 #include "assoc.h"
 #include "memory.h"
 #include "trigger.h"
-#include "coeio.h"
 
 static struct cord main_cord;
 __thread struct cord *cord_ptr = NULL;
@@ -76,12 +74,13 @@ fiber_call(struct fiber *callee, ...)
 	va_end(callee->f_data);
 }
 
-void
+bool
 fiber_checkstack()
 {
 	struct cord *cord = cord();
 	if (cord->sp + 1 - cord->stack >= FIBER_CALL_STACK)
-		tnt_raise(ClientError, ER_FIBER_STACK);
+		return true;
+	return false;
 }
 
 /** Interrupt a synchronous wait of a fiber inside the event loop.
@@ -397,10 +396,7 @@ fiber_loop(void *data __attribute__((unused)))
 		} catch (Exception *e) {
 			e->log();
 		} catch (...) {
-			/*
-			 * This can only happen in case of a bug
-			 * server bug.
-			 */
+			/* This can only happen in case of a server bug. */
 			say_error("fiber `%s': unknown exception",
 				fiber_name(fiber()));
 			panic("fiber `%s': exiting", fiber_name(fiber()));
@@ -638,29 +634,6 @@ cord_join(struct cord *cord)
 	return res;
 }
 
-ssize_t
-cord_cojoin_cb(va_list ap)
-{
-	struct cord *cord = va_arg(ap, struct cord *);
-	void *retval = NULL;
-	int res = tt_pthread_join(cord->id, &retval);
-	return res;
-}
-
-int
-cord_cojoin(struct cord *cord)
-{
-	assert(cord() != cord); /* Can't join self. */
-	int rc = coeio_custom(cord_cojoin_cb, TIMEOUT_INFINITY, cord);
-	if (rc == 0 && cord->exception) {
-		Exception::move(cord, cord());
-		cord_destroy(cord);
-		cord()->exception->raise(); /* re-throw exception from cord */
-	}
-	cord_destroy(cord);
-	return rc;
-}
-
 void
 fiber_init(void)
 {
diff --git a/src/fiber.h b/src/fiber.h
index c6433d0b90..3f72521aef 100644
--- a/src/fiber.h
+++ b/src/fiber.h
@@ -202,23 +202,14 @@ cord_start(struct cord *cord, const char *name,
 int
 cord_join(struct cord *cord);
 
-/**
- * \brief Yield until \a cord has terminated.
- * If \a cord has terminated with an uncaught exception
- * **re-throws** this exception in the calling cord/fiber.
- * \param cord cord
- * \sa pthread_join()
- * \return 0 on success
- */
-int
-cord_cojoin(struct cord *cord);
-
 static inline void
 cord_set_name(const char *name)
 {
 	snprintf(cord()->name, FIBER_NAME_MAX, "%s", name);
 }
 
+void
+cord_destroy(struct cord *cord);
 
 void fiber_init(void);
 void fiber_free(void);
@@ -233,7 +224,7 @@ fiber_name(struct fiber *f)
 	return region_name(&f->gc);
 }
 
-void
+bool
 fiber_checkstack();
 
 void fiber_yield(void);
diff --git a/src/iobuf.cc b/src/iobuf.cc
index 4f565693b4..07027ffffd 100644
--- a/src/iobuf.cc
+++ b/src/iobuf.cc
@@ -100,8 +100,7 @@ static inline void
 obuf_init_pos(struct obuf *buf, size_t pos)
 {
 	if (pos >= IOBUF_IOV_MAX) {
-		tnt_raise(LoggedError, ER_MEMORY_ISSUE, buf->pos,
-			  "obuf_init_pos", "iovec");
+		tnt_raise(OutOfMemory, buf->pos, "obuf_init_pos", "iovec");
 	}
 	buf->iov[pos].iov_base = NULL;
 	buf->iov[pos].iov_len = 0;
diff --git a/src/lib/small/mempool.h b/src/lib/small/mempool.h
index d465efa43c..8ce0056953 100644
--- a/src/lib/small/mempool.h
+++ b/src/lib/small/mempool.h
@@ -65,7 +65,7 @@ extern "C" {
  * ----------------
  * The only type of failure which can occur is a failure to
  * allocate memory. In case of such error, an exception
- * (ClientError, ER_OUT_OF_RESOURCES) is raised. _nothrow()
+ * (OutOfMemory) is raised. _nothrow()
  * version of mempool_alloc() returns NULL rather than raises an
  * error in case of failure.
  */
@@ -284,8 +284,8 @@ mempool_alloc(struct mempool *pool)
 {
 	void *ptr = mempool_alloc_nothrow(pool);
 	if (ptr == NULL)
-		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
-			  pool->objsize, "mempool", "new slab");
+		tnt_raise(OutOfMemory, pool->objsize,
+			  "mempool", "new slab");
 	return ptr;
 }
 
diff --git a/src/lib/small/region.h b/src/lib/small/region.h
index e06fbd4d4e..11adb988b7 100644
--- a/src/lib/small/region.h
+++ b/src/lib/small/region.h
@@ -232,8 +232,7 @@ region_alloc(struct region *region, size_t size)
 {
 	void *ptr = region_alloc_nothrow(region, size);
 	if (ptr == NULL)
-		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
-			  size, "region", "new slab");
+		tnt_raise(OutOfMemory, size, "region", "new slab");
 	return ptr;
 }
 
diff --git a/src/lib/small/small.h b/src/lib/small/small.h
index 6d77797b22..2efcab7e9d 100644
--- a/src/lib/small/small.h
+++ b/src/lib/small/small.h
@@ -277,8 +277,7 @@ smalloc(struct small_alloc *alloc, size_t size, const char *where)
 {
 	void *ptr = smalloc_nothrow(alloc, size);
 	if (ptr == NULL)
-		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
-			  size, "slab allocator", where);
+		tnt_raise(OutOfMemory, size, "slab allocator", where);
 	return ptr;
 }
 
diff --git a/src/lua/fiber.cc b/src/lua/fiber.cc
index 67094fba81..82e6ad1752 100644
--- a/src/lua/fiber.cc
+++ b/src/lua/fiber.cc
@@ -294,7 +294,10 @@ lbox_fiber_create(struct lua_State *L)
 {
 	if (lua_gettop(L) < 1 || !lua_isfunction(L, 1))
 		luaL_error(L, "fiber.create(function, ...): bad arguments");
-	fiber_checkstack();
+	if (fiber_checkstack()) {
+		lua_pushstring(L, "out of fiber stack");
+		tnt_raise(LuajitError, L);
+	}
 
 	struct fiber *f = fiber_new("lua", box_lua_fiber_run);
 	/* Not a system fiber. */
diff --git a/src/lua/init.cc b/src/lua/init.cc
index 7a39e454b7..f01a95f592 100644
--- a/src/lua/init.cc
+++ b/src/lua/init.cc
@@ -414,7 +414,7 @@ run_script(va_list ap)
 	}
 	try {
 		lbox_call(L, lua_gettop(L) - 1, 0);
-	} catch (ClientError *e) {
+	} catch (Exception *e) {
 		panic("%s", e->errmsg());
 	}
 
diff --git a/src/lua/trigger.cc b/src/lua/trigger.cc
index 3fafdd1cc4..a3bd8303ed 100644
--- a/src/lua/trigger.cc
+++ b/src/lua/trigger.cc
@@ -90,7 +90,7 @@ lbox_trigger_reset(struct lua_State *L, int top,
 		luaL_unref(L, LUA_REGISTRYINDEX, (intptr_t) trg->data);
 
 	} else if (lua_isfunction(L, top)) {
-		tnt_raise(ClientError, ER_NO_SUCH_TRIGGER);
+		luaL_error(L, "trigger reset: Trigger is not found");
 	}
 	/*
 	 * During update of a trigger, we must preserve its
diff --git a/src/lua/utils.cc b/src/lua/utils.cc
index 61f2786be6..6f68a5fc25 100644
--- a/src/lua/utils.cc
+++ b/src/lua/utils.cc
@@ -688,3 +688,11 @@ tarantool_lua_utils_init(struct lua_State *L)
 	fpconv_init();
 	return 0;
 }
+
+LuajitError::LuajitError(const char *file, unsigned line,
+			 struct lua_State *L)
+	:Exception(file, line)
+{
+	const char *msg = lua_tostring(L, -1);
+	snprintf(m_errmsg, sizeof(m_errmsg), "%s", msg ? msg : "");
+}
diff --git a/src/lua/utils.h b/src/lua/utils.h
index 055f87b11d..d023c32266 100644
--- a/src/lua/utils.h
+++ b/src/lua/utils.h
@@ -430,11 +430,12 @@ tarantool_lua_utils_init(struct lua_State *L);
 } /* extern "C" */
 
 #include "exception.h"
+class LuajitError: public Exception {
+public:
+	LuajitError(const char *file, unsigned line,
+		    struct lua_State *L);
+};
 
-/**
- * A wrapper around lua_call() which converts Lua error(...)
- * to ER_PROC_LUA
- */
 static inline void
 lbox_call(struct lua_State *L, int nargs, int nreturns)
 {
@@ -445,14 +446,15 @@ lbox_call(struct lua_State *L, int nargs, int nreturns)
 		throw;
 	} catch (...) {
 		/* Convert Lua error to a Tarantool exception. */
-		const char *msg = lua_tostring(L, -1);
-		tnt_raise(ClientError, ER_PROC_LUA, msg ? msg : "");
+		tnt_raise(LuajitError, L);
 	}
 }
 
 /**
  * Single global lua_State shared by core and modules.
  * Created with tarantool_lua_init().
+ * const char *msg = lua_tostring(L, -1);
+ * snprintf(m_errmsg, sizeof(m_errmsg), "%s", msg ? msg : "");
  */
 extern struct lua_State *tarantool_L;
 
diff --git a/src/pickle.h b/src/pickle.h
index 24315f945c..8c015b7bca 100644
--- a/src/pickle.h
+++ b/src/pickle.h
@@ -37,7 +37,6 @@
  * tuple and iproto binary formats.
  *
  * load_* - no boundary checking
- * pick_* - throws exception if no data in the buffer
  */
 
 static inline uint32_t
@@ -48,34 +47,6 @@ load_u32(const char **data)
 	return *b;
 }
 
-#define pick_u(bits)						\
-static inline uint##bits##_t					\
-pick_u##bits(const char **begin, const char *end)		\
-{								\
-	if (end - *begin < (bits)/8)				\
-		tnt_raise(IllegalParams,			\
-			  "packet too short (expected "#bits" bits)");\
-	uint##bits##_t r = *(uint##bits##_t *)*begin;		\
-	*begin += (bits)/8;					\
-	return r;						\
-}
-
-pick_u(8)
-pick_u(16)
-pick_u(32)
-pick_u(64)
-
-static inline const char *
-pick_str(const char **data, const char *end, uint32_t size)
-{
-	const char *str = *data;
-	if (str + size > end)
-		tnt_raise(IllegalParams,
-			  "packet too short (expected a field)");
-	*data += size;
-	return str;
-}
-
 #define pack_u(bits)						\
 static inline char *						\
 pack_u##bits(char *buf, uint##bits##_t val)			\
diff --git a/test/box/session.result b/test/box/session.result
index 49e15c2196..eb905aca72 100644
--- a/test/box/session.result
+++ b/test/box/session.result
@@ -80,11 +80,11 @@ session.on_disconnect()
 ...
 session.on_connect(function() end, function() end)
 ---
-- error: Trigger is not found
+- error: 'trigger reset: Trigger is not found'
 ...
 session.on_disconnect(function() end, function() end)
 ---
-- error: Trigger is not found
+- error: 'trigger reset: Trigger is not found'
 ...
 session.on_connect(1, 2)
 ---
diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt
index 0df204d057..1091ee26dd 100644
--- a/test/unit/CMakeLists.txt
+++ b/test/unit/CMakeLists.txt
@@ -49,12 +49,16 @@ target_link_libraries(rtree_itr.test)
 add_executable(matras.test matras.cc)
 target_link_libraries(matras.test small)
 add_executable(vclock.test vclock.cc test.c
-    ${CMAKE_SOURCE_DIR}/src/box/vclock.c)
-target_link_libraries(vclock.test core small
-    ${LIBEV_LIBRARIES} ${LIBEIO_LIBRARIES} ${LIBCORO_LIBRARIES})
+    ${CMAKE_SOURCE_DIR}/src/box/vclock.c
+    ${CMAKE_SOURCE_DIR}/src/box/errcode.c
+    ${CMAKE_SOURCE_DIR}/src/box/error.cc)
+target_link_libraries(vclock.test core small)
 add_executable(quota.test quota.cc test.c)
 target_link_libraries(quota.test pthread)
 
+add_executable(fiber.test fiber.cc)
+target_link_libraries(fiber.test core)
+
 set(MSGPUCK_DIR ${PROJECT_SOURCE_DIR}/src/lib/msgpuck/)
 add_executable(msgpack.test
     ${MSGPUCK_DIR}/test/msgpuck.c
diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc
new file mode 100644
index 0000000000..d851007323
--- /dev/null
+++ b/test/unit/fiber.cc
@@ -0,0 +1,10 @@
+#include "memory.h"
+#include "fiber.h"
+int main()
+{
+	memory_init();
+	fiber_init();
+	fiber_free();
+	memory_free();
+	return 0;
+}
diff --git a/test/unit/fiber.result b/test/unit/fiber.result
new file mode 100644
index 0000000000..e69de29bb2
-- 
GitLab