From fdc3d1dd2c3b120ff6426d074285908da7fb646d Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Thu, 17 Jul 2014 19:39:51 +0400
Subject: [PATCH] Implements gh-386; remove fiber.create(), fiber.resume(),
 fiber.detach()

Make status() a method.
Update the docs.
---
 doc/user/stored-procedures.xml | 108 ++--------
 src/box/space.cc               |   8 +-
 src/fiber.cc                   |   7 +
 src/fiber.h                    |   3 +
 src/lua/box_net_box.lua        |   6 +-
 src/lua/fiber.cc               | 322 ++----------------------------
 src/trigger.h                  |  12 ++
 test/app/init_script.result    |   2 +-
 test/app/init_script.test.lua  |   2 -
 test/box/box.net.box.result    |   2 +-
 test/box/box.net.box.test.lua  |   2 +-
 test/box/bsdsocket.result      |   4 +-
 test/box/bsdsocket.test.lua    |   4 +-
 test/box/configuration.test.py | 142 -------------
 test/box/fiber.result          | 354 +++++----------------------------
 test/box/fiber.test.lua        | 151 ++++----------
 test/box/ipc.result            |  14 +-
 test/box/ipc.test.lua          |  14 +-
 test/box/lua/fiber.lua         |  28 +--
 test/box/print.result          |   3 +-
 test/box/print.test.py         |   2 +-
 test/box/session.result        |  15 +-
 test/box/session.test.lua      |   7 +-
 test/box/socket.result         |   6 +-
 test/box/socket.test.py        |   6 +-
 test/box/suite.ini             |   2 +-
 test/box/transaction.result    |   2 +-
 test/box/transaction.test.lua  |   2 +-
 28 files changed, 208 insertions(+), 1022 deletions(-)
 delete mode 100644 test/box/configuration.test.py

diff --git a/doc/user/stored-procedures.xml b/doc/user/stored-procedures.xml
index c50ad8fd4f..14d006ebc5 100644
--- a/doc/user/stored-procedures.xml
+++ b/doc/user/stored-procedures.xml
@@ -822,22 +822,10 @@ tarantool> box.space.tester:insert{20,msgpack.NULL,20}
       called the <emphasis>fiber function</emphasis>.
 
       A fiber has three possible states: running, suspended or dead.
-      When a fiber is created with <code>fiber.create()</code>, it is suspended.
-      When a fiber is started with <code>fiber.resume()</code>, it is running.
-      When a fiber yields control with <code>fiber.yield()</code>, it is suspended.
+      When a fiber is created with <code>fiber.create()</code>, it is running.
+      When a fiber yields control with <code>fiber.sleep()</code>, it is suspended.
       When a fiber ends (because the fiber function ends), it is dead.
     </para>
-    <para>
-      A fiber can also be attached or detached.
-      An attached fiber is a child of the creator,
-      and is running only if the creator has called
-      <code>fiber.resume()</code>. A detached fiber is a child of
-      the Tarantool internal <quote>sched</quote> fiber, and gets
-      scheduled only if there is a libev event associated
-      with it.
-      To detach, a running fiber should invoke <code>fiber.wrap()</code>.
-      A detached fiber loses connection with its parent forever.
-    </para>
     <para>
       All fibers are part of the fiber registry.
       This registry can be searched (<code>fiber.find()</code>)
@@ -862,7 +850,7 @@ procedures.
 -->
     </para>
     <para>
-      The other potential problem comes from detached
+      The other potential problem comes from
       fibers which never get scheduled, because they are not subscribed
       to any events, or because no relevant events occur. Such morphing fibers
       can be killed with <code>fiber.cancel()</code> at any time,
@@ -895,7 +883,7 @@ procedures.
         </term>
         <listitem>
             <para>
-              Returns: (type = userdata) <code>require('fiber')</code>
+              Returns: (type = userdata) <code>fiber</code>
               object for the currently scheduled fiber.
             </para>
         </listitem>
@@ -910,104 +898,52 @@ procedures.
               Locate a fiber userdata object by id.
             </para>
             <para>
-              Returns: (type = userdata) require('fiber') object for the specified fiber.
-            </para>
-        </listitem>
-    </varlistentry>
-
-    <varlistentry>
-        <term>
-            <emphasis role="lua" xml:id="fiber.create">fiber.create(<replaceable>function-name</replaceable>) </emphasis>
-        </term>
-        <listitem>
-            <para>
-              Create a fiber.
-            </para>
-            <para>
-              Parameters: <code>function-name</code> = the function that the fiber is associated with.
-            </para>
-            <para>
-              Returns: (type = userdata) the require('fiber') object of the new fiber.
-            </para>
-            <para>
-              Possible errors: the function does not exist or if a recursion limit is hit.
+              Returns: (type = userdata) fiber object for the specified fiber.
             </para>
         </listitem>
     </varlistentry>
 
     <varlistentry>
         <term>
-            <emphasis role="lua" xml:id="fiber.resume">fiber.resume(<replaceable>fiber, ...</replaceable>) </emphasis>
+            <emphasis role="lua" xml:id="fiber.create">fiber.create(<replaceable>function, function-arguments</replaceable>)</emphasis>
         </term>
         <listitem>
             <para>
-              Resume a created
-              or suspended fiber.
+              Create and start a fiber. The fiber is
+              created and resumed immediately.
             </para>
-        </listitem>
-    </varlistentry>
-
-    <varlistentry>
-        <term>
-         <emphasis role="lua" xml:id="fiber.yield" xreflabel="fiber.yield">fiber.yield(<replaceable>yield-arguments</replaceable>) </emphasis>
-        </term>
-        <listitem>
             <para>
-              If the fiber is attached, yield control to the calling fiber if the fiber
-              is attached; otherwise, yield to sched.
-            </para>
-            <para>
-              Parameters: <code>yield-arguments</code>:  
-              If the fiber is attached, arguments passed
-              to fiber.yield are passed on to the calling fiber.
-              If the fiber is detached, <code>fiber.yield()</code>
-              arguments passed to fiber.yield are returned after temporarily
-              yielding control back to the scheduler.
-            </para>
-        </listitem>
-    </varlistentry>
-
-    <varlistentry>
-        <term>
-            <emphasis role="lua" xml:id="fiber.detach">fiber.detach()</emphasis>
-        </term>
-        <listitem>
-            <para>
-              Detach the current fiber. This is a cancellation point. This is a yield point.
-              It is usually more convenient to use <code>fiber.wrap()</code> to create
-              a fiber which is already detached when it is created.
+              Parameters: <code>function</code> = the function to be associated with the fiber,
+              <code>function-arguments</code> = what will be passed to the function.
             </para>
         </listitem>
     </varlistentry>
 
     <varlistentry>
         <term>
-            <emphasis role="lua" xml:id="fiber.wrap">fiber.wrap(<replaceable>function, function-arguments</replaceable>)</emphasis>
+            <emphasis role="lua" xml:id="fiber.sleep">fiber.sleep(<replaceable>time</replaceable>)</emphasis>
         </term>
         <listitem>
             <para>
-              This is a quick way to create and start a detached
-              fiber. The fiber is
-              created, detached, and resumed immediately.
+              Yield to the sched fiber and sleep for the specified number of seconds.
+              Only the current fiber can be made to sleep.
             </para>
             <para>
-              Parameters: <code>function</code> = the function to be associated with the fiber,
-              <code>function-arguments</code> = what will be passed to the function.
+              Parameters: <code>time</code> = number of seconds to sleep.
             </para>
         </listitem>
     </varlistentry>
 
     <varlistentry>
         <term>
-            <emphasis role="lua" xml:id="fiber.sleep">fiber.sleep(<replaceable>time</replaceable>)</emphasis>
+         <emphasis role="lua" xml:id="fiber.yield" xreflabel="fiber.yield">fiber.yield() </emphasis>
         </term>
         <listitem>
             <para>
-              Yield to the sched fiber and sleep for the specified number of seconds.
-              Only the current fiber can be made to sleep.
+              Yield control to the scheduler. Equivalent to <code>fiber.sleep(0)</code>.
             </para>
             <para>
-              Parameters: <code>time</code> = number of seconds to sleep.
+              Parameters: <code>none</code>.
             </para>
         </listitem>
     </varlistentry>
@@ -1135,12 +1071,12 @@ Make a fiber, associate function_x with the fiber,
 and start function_x. It will immediately "detach"
 so it will be running independently of the caller.
 <programlisting>
-<prompt>tarantool&gt;</prompt><userinput> fiber_of_x = fiber.wrap(function_x)</userinput>
+<prompt>tarantool&gt;</prompt><userinput> fiber_of_x = fiber.create(function_x)</userinput>
 ---
 ...</programlisting>
 
 Get the id of the fiber (fid), to be used in later displays.<programlisting>
-<prompt>tarantool&gt;</prompt><userinput> fid = fiber.wrap(function_x)</userinput>
+<prompt>tarantool&gt;</prompt><userinput> fid = fiber.create(function_x)</userinput>
 ---
 ...
 </programlisting>
@@ -1425,8 +1361,7 @@ end
             <para>
               Returns: (type = number) the unique identifier
               (ID) for the current session. The result can be 0 meaning
-              there is no session (for example because a function is
-              running in a detached fiber).
+              there is no session.
             </para>
       </listitem>
     </varlistentry>
@@ -1896,8 +1831,7 @@ with an Artistic license. The expirationd.lua program is
 lengthy (about 500 lines), so here we will only highlight
 the matters that will be enhanced by studying the full source later.
 <programlisting>
-            task.worker_fiber = fiber.create(worker_loop)
-            task.worker_fiber:resume(task)
+            task.worker_fiber = fiber.create(worker_loop, task)
             log.info("expiration: task %q restarted", task.name)
             ...
             fiber.sleep(expirationd.constants.check_interval)
diff --git a/src/box/space.cc b/src/box/space.cc
index ebfc0681ce..1247052a84 100644
--- a/src/box/space.cc
+++ b/src/box/space.cc
@@ -119,13 +119,7 @@ space_delete(struct space *space)
 	if (space->engine)
 		delete space->engine;
 
-	struct trigger *trigger, *tmp;
-	rlist_foreach_entry_safe(trigger, &space->on_replace, link, tmp) {
-		trigger_clear(trigger);
-		if (trigger->destroy)
-			trigger->destroy(trigger);
-
-	}
+	trigger_destroy(&space->on_replace);
 	free(space);
 }
 
diff --git a/src/fiber.cc b/src/fiber.cc
index dd24d949ad..dfed60327a 100644
--- a/src/fiber.cc
+++ b/src/fiber.cc
@@ -36,6 +36,7 @@
 #include "stat.h"
 #include "assoc.h"
 #include "memory.h"
+#include "trigger.h"
 
 static struct cord main_cord;
 __thread struct cord *cord_ptr = NULL;
@@ -201,6 +202,10 @@ fiber_yield(void)
 	struct fiber *callee = *(--cord->sp);
 	struct fiber *caller = cord->fiber;
 
+	/** By convention, these triggers must not throw. */
+	if (! rlist_empty(&caller->on_yield))
+		trigger_run(&caller->on_yield, NULL);
+
 	cord->fiber = callee;
 	update_last_stack_frame(caller);
 
@@ -441,6 +446,7 @@ fiber_new(const char *name, void (*f) (va_list))
 
 		rlist_add_entry(&cord->fibers, fiber, link);
 		rlist_create(&fiber->state);
+		rlist_create(&fiber->on_yield);
 	}
 
 	fiber->f = f;
@@ -472,6 +478,7 @@ fiber_destroy(struct fiber *f)
 	if (strcmp(fiber_name(f), "sched") == 0)
 		return;
 
+	trigger_destroy(&f->on_yield);
 	rlist_del(&f->state);
 	region_destroy(&f->gc);
 	tarantool_coro_destroy(&f->coro);
diff --git a/src/fiber.h b/src/fiber.h
index 9797f859d5..0dd014c8d7 100644
--- a/src/fiber.h
+++ b/src/fiber.h
@@ -99,6 +99,9 @@ struct fiber {
 	struct rlist link;
 	struct rlist state;
 
+	/** Triggers invoked before this fiber yields. Must not throw. */
+	struct rlist on_yield;
+
 	/* This struct is considered as non-POD when compiling by g++.
 	 * You can safetly ignore all offset_of-related warnings.
 	 * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31488
diff --git a/src/lua/box_net_box.lua b/src/lua/box_net_box.lua
index ae76dc81bb..517fe3fb07 100644
--- a/src/lua/box_net_box.lua
+++ b/src/lua/box_net_box.lua
@@ -353,9 +353,9 @@ local remote_methods = {
         self.timeouts = {}
 
 
-        fiber.wrap(function() self:_connect_worker() end)
-        fiber.wrap(function() self:_read_worker() end)
-        fiber.wrap(function() self:_write_worker() end)
+        fiber.create(function() self:_connect_worker() end)
+        fiber.create(function() self:_read_worker() end)
+        fiber.create(function() self:_write_worker() end)
 
         if self.opts.wait_connected == nil or self.opts.wait_connected then
             self:wait_connected()
diff --git a/src/lua/fiber.cc b/src/lua/fiber.cc
index 8300a12c2d..72a04d7fd9 100644
--- a/src/lua/fiber.cc
+++ b/src/lua/fiber.cc
@@ -45,23 +45,8 @@ extern "C" {
 /* {{{ box.fiber Lua library: access to Tarantool fibers
  *
  * Each fiber can be running, suspended or dead.
- * A fiber is created (fiber.create()) suspended.
- * It can be started with fiber.resume(), yield
- * the control back with fiber.yield() end
- * with return or just by reaching the end of the
- * function.
- *
- * A fiber can also be attached or detached.
- * An attached fiber is a child of the creator,
- * and is running only if the creator has called
- * fiber.resume(). A detached fiber is a child of
- * Tarntool/Box internal 'sched' fiber, and gets
- * scheduled only if there is a libev event associated
- * with it.
- * To detach itself, a running fiber must invoke
- * fiber.detach().
- * A detached fiber loses connection with its parent
- * forever.
+ * When a fiber is created (fiber.create()) it's
+ * running.
  *
  * All fibers are part of the fiber registry, fiber.
  * This registry can be searched either by
@@ -85,7 +70,7 @@ extern "C" {
  * if it does a lot of computations and doesn't check
  * whether it's been cancelled (just don't do that).
  *
- * The other potential problem comes from detached
+ * The other potential problem comes from
  * fibers which never get scheduled, because are subscribed
  * or get no events. Such morphing fibers can be killed
  * with fiber.cancel(), since fiber.cancel()
@@ -94,7 +79,7 @@ extern "C" {
 
 static const char *fiberlib_name = "fiber";
 
-enum fiber_state { DONE, YIELD, DETACH };
+enum fiber_state { DONE, YIELD };
 
 /**
  * @pre: stack top contains a table
@@ -179,7 +164,7 @@ lbox_checkfiber(struct lua_State *L, int index)
 	uint32_t fid = *(uint32_t *) luaL_checkudata(L, index, fiberlib_name);
 	struct fiber *f = fiber_find(fid);
 	if (f == NULL)
-		luaL_error(L, "fiber.resume(): the fiber is dead");
+		luaL_error(L, "the fiber is dead");
 	return f;
 }
 
@@ -222,46 +207,6 @@ box_lua_fiber_clear_coro(struct lua_State *L, struct fiber *f)
 	lua_settable(L, LUA_REGISTRYINDEX);
 }
 
-/**
- * To yield control to the calling fiber
- * we need to be able to find the caller of an
- * attached fiber. Instead of passing the caller
- * around on the child fiber stack, we create a
- * weak table associated with child fiber
- * lua_State, and save the caller in it.
- *
- * When the child fiber lua thread is garbage collected,
- * the table is automatically cleared.
- */
-static void
-box_lua_fiber_push_caller(struct lua_State *child_L)
-{
-	luaL_getmetatable(child_L, fiberlib_name);
-	lua_getfield(child_L, -1, "callers");
-	if (lua_isnil(child_L, -1)) {
-		lua_pop(child_L, 1);
-		lbox_create_weak_table(child_L, "callers");
-	}
-	lua_pushthread(child_L);
-	lua_pushinteger(child_L, fiber()->fid);
-	lua_settable(child_L, -3);
-	/* Pop the fiberlib metatable and callers table. */
-	lua_pop(child_L, 2);
-}
-
-static struct fiber *
-box_lua_fiber_get_caller(struct lua_State *L)
-{
-	luaL_getmetatable(L, fiberlib_name);
-	lua_getfield(L, -1, "callers");
-	lua_pushthread(L);
-	lua_gettable(L, -2);
-	struct fiber *caller = fiber_find(lua_tointeger(L, -1));
-	/* Pop the caller, the callers table, the fiberlib metatable. */
-	lua_pop(L, 3);
-	return caller;
-}
-
 static int
 lbox_fiber_gc(struct lua_State *L)
 {
@@ -365,124 +310,6 @@ lbox_fiber_info(struct lua_State *L)
 	return 1;
 }
 
-/**
- * Detach the current fiber.
- */
-static int
-lbox_fiber_detach(struct lua_State *L)
-{
-	if (box_lua_fiber_get_coro(L, fiber()) == NULL)
-		luaL_error(L, "fiber.detach(): not attached");
-	struct fiber *caller = box_lua_fiber_get_caller(L);
-	/* Clear the caller, to avoid a reference leak. */
-	/* Request a detach. */
-	lua_pushinteger(L, DETACH);
-	fiber_yield_to(caller);
-	return 0;
-}
-
-static void
-box_lua_fiber_run(va_list ap __attribute__((unused)))
-{
-	fiber_testcancel();
-	fiber_setcancellable(false);
-
-	struct lua_State *L = box_lua_fiber_get_coro(tarantool_L, fiber());
-	/*
-	 * Reference the coroutine to make sure it's not garbage
-	 * collected when detached.
-	 */
-	lua_pushthread(L);
-	LuarefGuard coro_guard(L);
-        SessionGuard session_guard(-1, 0);
-	/*
-	 * Lua coroutine.resume() returns true/false for
-	 * completion status plus whatever the coroutine main
-	 * function returns. Follow this style here.
-	 */
-	try {
-		lbox_call(L, lua_gettop(L) - 1, LUA_MULTRET);
-		/* push completion status */
-		lua_pushboolean(L, true);
-		/* move 'true' to stack start */
-		lua_insert(L, 1);
-	} catch (FiberCancelException *e) {
-		if (box_lua_fiber_get_coro(L, fiber())) {
-			struct fiber *caller = box_lua_fiber_get_caller(L);
-			fiber_wakeup(caller);
-		}
-		box_lua_fiber_clear_coro(tarantool_L, fiber());
-		/*
-		 * Note: FiberCancelException leaves garbage on
-		 * coroutine stack. This is OK since it is only
-		 * possible to cancel a fiber which is not
-		 * scheduled, and cancel() is synchronous.
-		 */
-
-		throw;
-	} catch (Exception *e) {
-		/* pop any possible garbage */
-		lua_settop(L, 0);
-		/* completion status */
-		lua_pushboolean(L, false);
-		/* error message */
-		lua_pushstring(L, e->errmsg());
-
-		/* Always log the error. */
-		e->log();
-	}
-	/*
-	 * L stack contains nothing but call results.
-	 * If we're still attached, synchronously pass
-	 * them to the caller, and then terminate.
-	 */
-	if (box_lua_fiber_get_coro(L, fiber())) {
-		struct fiber *caller = box_lua_fiber_get_caller(L);
-		lua_pushinteger(L, DONE);
-		fiber_yield_to(caller);
-	}
-}
-
-/** @retval true if check failed, false otherwise */
-static bool
-lbox_fiber_checkstack(struct lua_State *L)
-{
-	fiber_checkstack();
-	struct fiber *f = fiber();
-	const int MAX_STACK_DEPTH = 16;
-	int depth = 1;
-	while ((L = box_lua_fiber_get_coro(L, f)) != NULL) {
-		if (depth++ == MAX_STACK_DEPTH)
-			return true;
-		f = box_lua_fiber_get_caller(L);
-	}
-	return false;
-}
-
-
-static int
-lbox_fiber_create(struct lua_State *L)
-{
-	if (lua_gettop(L) != 1 || !lua_isfunction(L, 1))
-		luaL_error(L, "fiber.create(function): bad arguments");
-	if (lbox_fiber_checkstack(L))
-		luaL_error(L, "fiber.create(function): recursion limit"
-			   " reached");
-
-	struct fiber *f = fiber_new("lua", box_lua_fiber_run);
-	/* Initially the fiber is cancellable */
-	f->flags |= FIBER_USER_MODE | FIBER_CANCELLABLE;
-
-	/* associate coro with fiber */
-	lua_pushlightuserdata(L, f);
-	struct lua_State *child_L = lua_newthread(L);
-	lua_settable(L, LUA_REGISTRYINDEX);
-	/* Move the argument (function of the coro) to the new coro */
-	lua_xmove(L, child_L, 1);
-	lbox_pushfiber(L, f);
-	return 1;
-}
-
 static int
 lbox_fiber_wakeup(struct lua_State *L)
 {
@@ -491,65 +318,6 @@ lbox_fiber_wakeup(struct lua_State *L)
 	return 0;
 }
 
-static int
-lbox_fiber_resume(struct lua_State *L)
-{
-	struct fiber *f = lbox_checkfiber(L, 1);
-	struct lua_State *child_L = box_lua_fiber_get_coro(L, f);
-	if (child_L == NULL)
-		luaL_error(L, "fiber.resume(): can't resume a "
-			   "detached fiber");
-	int nargs = lua_gettop(L) - 1;
-	if (nargs > 0)
-		lua_xmove(L, child_L, nargs);
-	/* dup 'out' for admin fibers */
-	int fid = f->fid;
-	/* Silent compiler warnings in a release build. */
-	(void) fid;
-	box_lua_fiber_push_caller(child_L);
-	/*
-	 * We don't use fiber_call() since this breaks any sort
-	 * of yield in the called fiber: for a yield to work,
-	 * the callee got to be scheduled by 'sched'.
-	 */
-	fiber_yield_to(f);
-	/*
-	 * The called fiber could have done 4 things:
-	 * - yielded to us (then we should grab its return)
-	 * - completed (grab return values, wake up the fiber,
-	 *   so that it can die)
-	 * - detached (grab return values, wakeup the fiber so it
-	 *   can continue).
-	 * - got cancelled (return)
-	 */
-	if (f->fid != fid)
-		luaL_error(L, "fiber.resume(): the child fiber got cancelled");
-	/* Find out the state of the child fiber. */
-	enum fiber_state child_state = (enum fiber_state) lua_tointeger(child_L, -1);
-	lua_pop(child_L, 1);
-	/* Get the results */
-	nargs = lua_gettop(child_L);
-	lua_xmove(child_L, L, nargs);
-	if (child_state != YIELD) {
-		/*
-		 * The fiber is dead or requested a detach.
-		 * Garbage collect the associated coro.
-		 */
-		box_lua_fiber_clear_coro(L, f);
-		if (child_state == DETACH) {
-			/*
-			 * Schedule the runaway child at least
-			 * once.
-			 */
-			fiber_wakeup(f);
-		} else {
-			/* Synchronously reap a dead child. */
-			fiber_call(f);
-		}
-	}
-	return nargs;
-}
-
 static void
 box_lua_fiber_run_detached(va_list ap)
 {
@@ -571,10 +339,10 @@ box_lua_fiber_run_detached(va_list ap)
  * given the function and its arguments.
  */
 static int
-lbox_fiber_wrap(struct lua_State *L)
+lbox_fiber_create(struct lua_State *L)
 {
 	if (lua_gettop(L) < 1 || !lua_isfunction(L, 1))
-		luaL_error(L, "fiber.wrap(function, ...): bad arguments");
+		luaL_error(L, "fiber.create(function, ...): bad arguments");
 	fiber_checkstack();
 
 	struct fiber *f = fiber_new("lua", box_lua_fiber_run_detached);
@@ -584,65 +352,11 @@ lbox_fiber_wrap(struct lua_State *L)
 	int coro_ref = luaL_ref(L, LUA_REGISTRYINDEX);
 	/* Move the arguments to the new coro */
 	lua_xmove(L, child_L, lua_gettop(L));
+	lbox_pushfiber(L, f);
 	fiber_call(f, coro_ref, child_L);
-	if (f->fid)
-		lbox_pushfiber(L, f);
-	else
-		lua_pushnil(L);
 	return 1;
 }
 
-/**
- * Yield the current fiber.
- *
- * Yield control to the calling fiber -- if the fiber
- * is attached, or to sched otherwise.
- * If the fiber is attached, whatever arguments are passed
- * to this call, are passed on to the calling fiber.
- * If the fiber is detached, simply returns everything back.
- */
-static int
-lbox_fiber_yield(struct lua_State *L)
-{
-	/*
-	 * Yield to the caller. The caller will take care of
-	 * whatever arguments are taken.
-	 */
-	fiber_setcancellable(true);
-	struct lua_State *coro_L;
-	struct fiber *caller;
-	if ((coro_L = box_lua_fiber_get_coro(L, fiber())) &&
-	     (caller = box_lua_fiber_get_caller(coro_L))) {
-		lua_pushinteger(L, YIELD);
-		fiber_yield_to(caller);
-	} else {
-		fiber_wakeup(fiber());
-		fiber_yield();
-		fiber_testcancel();
-	}
-	fiber_setcancellable(false);
-	/*
-	 * Got resumed. Return whatever the caller has passed
-	 * to us with fiber.resume().
-	 * As a side effect, the detached fiber which yields
-	 * to sched always gets back whatever it yields.
-	 */
-	return lua_gettop(L);
-}
-
-static bool
-fiber_is_caller(struct lua_State *L, struct fiber *f)
-{
-	struct fiber *child = fiber();
-	while ((L = box_lua_fiber_get_coro(L, child)) != NULL) {
-		struct fiber *caller = box_lua_fiber_get_caller(L);
-		if (caller == f)
-			return true;
-		child = caller;
-	}
-	return false;
-}
-
 /**
  * Get fiber status.
  * This follows the rules of Lua coroutine.status() function:
@@ -673,9 +387,6 @@ lbox_fiber_status(struct lua_State *L)
 	} else if (f == fiber()) {
 		/* The fiber is the current running fiber. */
 		status = "running";
-	} else if (fiber_is_caller(L, f)) {
-		/* The fiber is current fiber's caller. */
-		status = "normal";
 	} else {
 		/* None of the above: must be suspended. */
 		status = "suspended";
@@ -727,6 +438,15 @@ lbox_fiber_sleep(struct lua_State *L)
 	return 0;
 }
 
+static int
+lbox_fiber_yield(struct lua_State * /* L */)
+{
+	fiber_setcancellable(true);
+	fiber_sleep(0);
+	fiber_setcancellable(false);
+	return 0;
+}
+
 static int
 lbox_fiber(struct lua_State *L)
 {
@@ -798,7 +518,8 @@ static const struct luaL_reg lbox_fiber_meta [] = {
 	{"name", lbox_fiber_name},
 	{"wakeup", lbox_fiber_wakeup},
 	{"cancel", lbox_fiber_cancel},
-	{"resume", lbox_fiber_resume},
+	{"status", lbox_fiber_status},
+	{"testcancel", lbox_fiber_testcancel},
 	{"__gc", lbox_fiber_gc},
 	{NULL, NULL}
 };
@@ -806,18 +527,15 @@ static const struct luaL_reg lbox_fiber_meta [] = {
 static const struct luaL_reg fiberlib[] = {
 	{"info", lbox_fiber_info},
 	{"sleep", lbox_fiber_sleep},
+	{"yield", lbox_fiber_yield},
 	{"self", lbox_fiber},
 	{"id", lbox_fiber_id},
 	{"find", lbox_fiber_find},
 	{"cancel", lbox_fiber_cancel},
 	{"testcancel", lbox_fiber_testcancel},
 	{"create", lbox_fiber_create},
-	{"resume", lbox_fiber_resume},
-	{"wrap", lbox_fiber_wrap},
-	{"yield", lbox_fiber_yield},
 	{"status", lbox_fiber_status},
 	{"name", lbox_fiber_name},
-	{"detach", lbox_fiber_detach},
 	{"time", lbox_fiber_time},
 	{"time64", lbox_fiber_time64},
 	{NULL, NULL}
diff --git a/src/trigger.h b/src/trigger.h
index d230c3d88a..c64f05942e 100644
--- a/src/trigger.h
+++ b/src/trigger.h
@@ -92,4 +92,16 @@ trigger_clear(struct trigger *trigger)
 	rlist_del_entry(trigger, link);
 }
 
+
+static inline void
+trigger_destroy(struct rlist *list)
+{
+	struct trigger *trigger, *tmp;
+	rlist_foreach_entry_safe(trigger, list, link, tmp) {
+		trigger_clear(trigger);
+		if (trigger->destroy)
+			trigger->destroy(trigger);
+	}
+}
+
 #endif /* INCLUDES_TARANTOOL_TRIGGER_H */
diff --git a/test/app/init_script.result b/test/app/init_script.result
index beb3341132..ce6ab4aa1b 100644
--- a/test/app/init_script.result
+++ b/test/app/init_script.result
@@ -28,7 +28,7 @@ box.cfg
 --
 
 ---
-[]
+- [1, 2, 4, 8]
 ...
 
 --
diff --git a/test/app/init_script.test.lua b/test/app/init_script.test.lua
index 41b523858a..4bc28a7a00 100755
--- a/test/app/init_script.test.lua
+++ b/test/app/init_script.test.lua
@@ -34,12 +34,10 @@ for k,v in pairs(t) do print(k, v) end
 -- Insert tests
 --
 local function do_insert()
-    fiber.detach()
     space:insert{1, 2, 4, 8}
 end
 
 fiber1 = fiber.create(do_insert)
-fiber.resume(fiber1)
 
 print[[
 --
diff --git a/test/box/box.net.box.result b/test/box/box.net.box.result
index d410e5032e..907414a7e5 100644
--- a/test/box/box.net.box.result
+++ b/test/box/box.net.box.result
@@ -302,7 +302,7 @@ cn:_select(space.id, 0, {}, { iterator = 'ALL' })
   - [354, 1, 2, 4]
 ...
 -- -- error while waiting for response
-type(fiber.wrap(function() fiber.sleep(.5) cn:_fatal('Test error') end))
+type(fiber.create(function() fiber.sleep(.5) cn:_fatal('Test error') end))
 ---
 - userdata
 ...
diff --git a/test/box/box.net.box.test.lua b/test/box/box.net.box.test.lua
index 68e9356a6d..4911ce6a90 100644
--- a/test/box/box.net.box.test.lua
+++ b/test/box/box.net.box.test.lua
@@ -109,7 +109,7 @@ cn:_fatal 'Test error'
 cn:_select(space.id, 0, {}, { iterator = 'ALL' })
 
 -- -- error while waiting for response
-type(fiber.wrap(function() fiber.sleep(.5) cn:_fatal('Test error') end))
+type(fiber.create(function() fiber.sleep(.5) cn:_fatal('Test error') end))
 function pause() fiber.sleep(10) return true end
 
 cn:call('pause')
diff --git a/test/box/bsdsocket.result b/test/box/bsdsocket.result
index 4c9fb2fdf4..2beae4da82 100644
--- a/test/box/bsdsocket.result
+++ b/test/box/bsdsocket.result
@@ -183,7 +183,7 @@ s:listen(128)
 sevres = {}
 ---
 ...
-type(require('fiber').wrap(function() s:readable() do local sc = s:accept() table.insert(sevres, sc) sc:syswrite('ok') sc:close() end end))
+type(require('fiber').create(function() s:readable() do local sc = s:accept() table.insert(sevres, sc) sc:syswrite('ok') sc:close() end end))
 ---
 - userdata
 ...
@@ -832,7 +832,7 @@ sa:writable(0)
 ch = fiber.channel()
 ---
 ...
-f = fiber.wrap(function() s:read(12) ch:put(true) end)
+f = fiber.create(function() s:read(12) ch:put(true) end)
 ---
 ...
 fiber.sleep(.1)
diff --git a/test/box/bsdsocket.test.lua b/test/box/bsdsocket.test.lua
index 43a87179bb..394065bf9a 100644
--- a/test/box/bsdsocket.test.lua
+++ b/test/box/bsdsocket.test.lua
@@ -58,7 +58,7 @@ s:bind('127.0.0.1', 3457)
 s:error()
 s:listen(128)
 sevres = {}
-type(require('fiber').wrap(function() s:readable() do local sc = s:accept() table.insert(sevres, sc) sc:syswrite('ok') sc:close() end end))
+type(require('fiber').create(function() s:readable() do local sc = s:accept() table.insert(sevres, sc) sc:syswrite('ok') sc:close() end end))
 #sevres
 
 sc = socket('PF_INET', 'SOCK_STREAM', 'tcp')
@@ -266,7 +266,7 @@ sa:readable(0)
 sa:writable(0)
 
 ch = fiber.channel()
-f = fiber.wrap(function() s:read(12) ch:put(true) end)
+f = fiber.create(function() s:read(12) ch:put(true) end)
 fiber.sleep(.1)
 s:close()
 ch:get(1)
diff --git a/test/box/configuration.test.py b/test/box/configuration.test.py
deleted file mode 100644
index d311508eb1..0000000000
--- a/test/box/configuration.test.py
+++ /dev/null
@@ -1,142 +0,0 @@
-import os
-import sys
-import shutil
-
-# mask BFD warnings: https://bugs.launchpad.net/tarantool/+bug/1018356
-sys.stdout.push_filter("unable to read unknown load command 0x2\d+", "")
-
-print """
-# Bug #876541:
-#  Test floating point values (wal_fsync_delay) with fractional part
-#  (https://bugs.launchpad.net/bugs/876541)
-"""
-# stop current server
-server.stop()
-
-old_cfgfile = server.cfgfile_source
-server.cfgfile_source = "box/tarantool_bug876541.cfg"
-server.deploy()
-# check values
-admin("box.cfg.wal_fsync_delay")
-
-server.stop()
-server.cfgfile_source = old_cfgfile
-old_script = server.script
-server.script = "box/lua/test_init.lua"
-server.deploy()
-sys.stdout.push_filter("admin: .*", "admin: <uri>")
-sys.stdout.push_filter("listen: .*", "listen: <uri>")
-admin("print_config()")
-sys.stdout.pop_filter()
-sys.stdout.pop_filter()
-
-print """
-# Test bug #977898
-"""
-# Run a dummy insert to avoid race conditions under valgrind
-admin("box.space.tweedledum:insert{4, 8, 16}")
-
-print """
-# Test insert from init.lua
-"""
-admin("box.space.tweedledum:get(1)")
-admin("box.space.tweedledum:get(2)")
-admin("box.space.tweedledum:get(4)")
-
-print """
-# Test bug #1002272
-"""
-admin("floor(0.5)")
-admin("floor(0.9)")
-admin("floor(1.1)")
-server.stop()
-server.script = old_script
-
-# Test script_dir + require
-old_script = server.script
-server.script = "box/lua/require_init.lua"
-server.lua_libs.append("box/lua/require_mod.lua")
-server.deploy()
-server.lua_libs.pop()
-admin("mod.test(10, 15)")
-server.stop()
-server.script = old_script
-
-
-print """
-# Bug#99 Salloc initialization is not checked on startup
-#  (https://github.com/tarantool/tarantool/issues/99)
-"""
-old_cfgfile = server.cfgfile_source
-server.cfgfile_source="box/tarantool_bug_gh-99.cfg"
-try:
-    server.deploy()
-except OSError as e:
-    print e
-    print("ok")
-server.stop()
-server.cfgfile_source = old_cfgfile
-
-print """
-# Bug#100 Segmentation fault if rows_per_wal = 0
-#  (https://github.com/tarantool/tarantool/issues/100)
-"""
-old_cfgfile = server.cfgfile_source
-server.cfgfile_source = "box/tarantool_bug_gh100.cfg"
-try:
-    server.deploy()
-except OSError as e:
-    print e
-    print("ok")
-server.stop()
-server.cfgfile_source = old_cfgfile
-print """#
-# Check that --background  doesn't work if there is no logger
-# This is a test case for
-# https://bugs.launchpad.net/tarantool/+bug/750658
-# "--background neither closes nor redirects stdin/stdout/stderr"
-"""
-old_cfgfile = server.cfgfile_source
-server.cfgfile_source = "box/tarantool_bug750658.cfg"
-try:
-    server.deploy()
-except OSError as e:
-    print e
-    print("ok")
-
-server.stop()
-server.cfgfile_source = old_cfgfile
-print """
-# A test case for Bug#726778 "Gopt broke wal_dir and snap_dir: they are no
-# longer relative to work_dir".
-# https://bugs.launchpad.net/tarantool/+bug/726778
-# After addition of gopt(), we started to chdir() to the working
-# directory after option parsing.
-# Verify that this is not the case, and snap_dir and xlog_dir
-# can be relative to work_dir.
-"""
-import shutil
-vardir = server.vardir
-shutil.rmtree(os.path.join(vardir, "bug726778"), True)
-os.mkdir(os.path.join(vardir, "bug726778"))
-os.mkdir(os.path.join(vardir, "bug726778/snapshots"))
-os.mkdir(os.path.join(vardir, "bug726778/xlogs"))
-
-sys.stdout.push_filter("(/\S+)+/tarantool", "tarantool")
-sys.stdout.push_filter(".*(P|p)lugin.*", "")
-sys.stdout.push_filter(".*shared.*", "")
-old_cfgfile = server.cfgfile_source
-old_logfile = server.logfile
-# make sure deploy() looks for start message in a correct
-# place
-server.logfile = os.path.join(vardir, "bug726778/tarantool.log")
-server.cfgfile_source = "box/bug726778.cfg"
-server.deploy()
-sys.stdout.clear_all_filters()
-server.stop()
-shutil.rmtree(os.path.join(vardir, "bug726778"))
-server.cfgfile_source = old_cfgfile
-server.logfile = old_logfile
-
-# restore default server
-server.deploy()
diff --git a/test/box/fiber.result b/test/box/fiber.result
index a6f61ceb1f..7d6971c765 100644
--- a/test/box/fiber.result
+++ b/test/box/fiber.result
@@ -215,7 +215,6 @@ space:truncate()
 -- test passing arguments in and out created fiber
 --# setopt delimiter ';'
 function y()
-    fiber.detach('started')
     space = box.space['tweedledum']
     while true do
         space:replace{1953719668, os.time()}
@@ -227,24 +226,17 @@ end;
 f = fiber.create(y);
 ---
 ...
-fiber.resume(f);
----
-- started
-...
 fiber.sleep(0.002);
 ---
 ...
 fiber.cancel(f);
 ---
 ...
-fiber.resume(f);
----
-- error: 'fiber.resume(): the fiber is dead'
-...
+-- fiber garbage collection
 for k = 1, 1000, 1 do
     fiber.create(
         function()
-            fiber.detach()
+            fiber.sleep(0)
         end
     )
 end;
@@ -281,44 +273,40 @@ fiber.find('test')
 f = fiber.create(function() fiber.cancel(fiber.self()) end)
 ---
 ...
-fiber.resume(f)
----
-- error: 'fiber.resume(): the child fiber got cancelled'
-...
 f = nil
 ---
 ...
 -- https://github.com/tarantool/tarantool/issues/119
-ftest = function() fiber.sleep(0.01 * math.random() ) return true end
+ftest = function() fiber.sleep(0.0001 * math.random() ) return true end
 ---
 ...
 --# setopt delimiter ';'
+result = 0;
+---
+...
 for i = 1, 10 do
-    result = {}
+    local res = {}
     for j = 1, 300 do
-        fiber.resume(fiber.create(function()
-            fiber.detach()
-            table.insert(result, ftest())
-        end))
+        fiber.create(function() table.insert(res, ftest()) end)
     end
-    while #result < 300 do fiber.sleep(0.01) end
+    while #res < 300 do fiber.sleep(0) end
+    result = result + #res
 end;
 ---
 ...
 --# setopt delimiter ''
-#result
+result
 ---
-- 300
+- 3000
 ...
---# setopt delimiter ''
 --
 -- 
---  Test fiber.wrap()
+--  Test fiber.create()
 -- 
 --  This should try to infinitely create fibers,
 --  but hit the fiber stack size limit and fail
 --  with an error.
-f = function() fiber.wrap(f) end
+f = function() fiber.create(f) end
 ---
 ...
 f()
@@ -327,7 +315,7 @@ f()
 -- 
 -- Test argument passing
 -- 
-f = function(a, b) fiber.wrap(function(arg) result = arg end, a..b) end
+f = function(a, b) fiber.create(function(arg) result = arg end, a..b) end
 ---
 ...
 f('hello ', 'world')
@@ -347,9 +335,8 @@ result
 -- 
 -- Test that the created fiber is detached
 -- 
-fiber.wrap(function() result = fiber.status() end)
+local f = fiber.create(function() result = fiber.status() end)
 ---
-- null
 ...
 result
 ---
@@ -358,7 +345,7 @@ result
 -- A test case for Bug#933487
 -- tarantool crashed during shutdown if non running LUA fiber
 -- was created
-f = fiber.create(function () return true end)
+f = fiber.create(function () fiber.sleep(1) return true end)
 ---
 ...
 box.snapshot()
@@ -373,14 +360,10 @@ box.snapshot()
 ---
 - error: can't save snapshot, errno 17 (File exists)
 ...
-fiber.resume(f)
----
-- true
-- true
-...
-f = fiber.create(function () return true end)
+f = fiber.create(function () fiber.sleep(1) end)
 ---
 ...
+-- Test fiber.sleep()
 fiber.sleep(0)
 ---
 ...
@@ -398,6 +381,7 @@ fiber.sleep(box, 0.001)
 ---
 - error: 'fiber.sleep(delay): bad arguments'
 ...
+-- test fiber.self()
 fiber.cancel(fiber.self())
 ---
 - error: 'fiber.cancel(): subject fiber does not permit cancel'
@@ -431,105 +415,58 @@ f==g
 ---
 - true
 ...
-function r() f = fiber.create(r) return (fiber.resume(f)) end
----
-...
-r()
----
-- true
-...
+-- arguments to fiber.create
 f = fiber.create(print('hello'))
 ---
-- error: '[string "f = fiber.create(print(''hello'')) "]:1: fiber.create(function):
-    bad arguments'
-...
-fiber.resume(f)
----
-- error: 'fiber.resume(): the fiber is dead'
+- error: '[string "f = fiber.create(print(''hello'')) "]:1: fiber.create(function,
+    ...): bad arguments'
 ...
 -- test passing arguments in and out created fiber
-function r(a, b) return a, b end
+function r(a, b) res = { a, b } end
 ---
 ...
 f=fiber.create(r)
 ---
 ...
-fiber.resume(f)
----
-- true
-- null
-- null
-...
-f=fiber.create(r)
----
-...
-fiber.resume(f, 'hello')
----
-- true
-- hello
-- null
-...
-f=fiber.create(r)
----
-...
-fiber.resume(f, 'hello', 'world')
----
-- true
-- hello
-- world
-...
-f=fiber.create(r)
----
-...
-fiber.resume(f, 'hello', 'world', 'wide')
----
-- true
-- hello
-- world
-...
-function y(a, b) c=fiber.yield(a) return fiber.yield(b, c) end
----
-...
-f=fiber.create(y)
+while f:status() == 'running' do fiber.sleep(0) end
 ---
 ...
-fiber.resume(f, 'hello', 'world')
+res
 ---
-- hello
+- []
 ...
-fiber.resume(f, 'wide')
+f=fiber.create(r, 'hello')
 ---
-- world
-- wide
 ...
-fiber.resume(f)
+while f:status() == 'running' do fiber.sleep(0) end
 ---
-- true
 ...
-function y() fiber.detach() while true do box.replace(0, 1953719668, os.time()) fiber.sleep(0.001) end end
+res
 ---
+- - hello
 ...
-f = fiber.create(y)
+f=fiber.create(r, 'hello, world')
 ---
 ...
-fiber.resume(f)
+while f:status() == 'running' do fiber.sleep(0) end
 ---
 ...
-fiber.sleep(0.002)
+res
 ---
+- - hello, world
 ...
-fiber.cancel(f)
+f=fiber.create(r, 'hello', 'world', 'wide')
 ---
-- error: 'fiber.resume(): the fiber is dead'
 ...
-fiber.resume(f)
+while f:status() == 'running' do fiber.sleep(0) end
 ---
-- error: 'fiber.resume(): the fiber is dead'
 ...
-f=nil
+res
 ---
+- - hello
+  - world
 ...
-for k=1, 10000, 1 do fiber.create(function() fiber.detach() end) end
+for k=1, 10000, 1 do fiber.create(function() fiber.sleep(0) end) end
 ---
 ...
 collectgarbage('collect')
@@ -562,196 +499,19 @@ fiber.status(nil)
 ---
 - error: 'bad argument #1 to ''?'' (fiber expected, got nil)'
 ...
---  A test case for Bug#911641 fiber.sleep() works incorrectly if
---  a fiber is attached.
-function r() return fiber.sleep(0.01) end
----
-...
-f = fiber.create(r)
----
-...
-fiber.resume(f)
----
-- true
-...
-fiber.resume(f)
----
-- error: 'fiber.resume(): the fiber is dead'
-...
---# setopt delimiter ';'
-function r()
-    fiber.yield(box.space.tweedledum:insert{0, 0, 1})
-    fiber.yield(box.space.tweedledum:get{0})
-    fiber.yield(box.space.tweedledum:truncate())
-end;
----
-...
---# setopt delimiter ''
-f = fiber.create(r)
----
-...
-fiber.resume(f)
----
-- [0, 0, 1]
-...
-fiber.resume(f)
----
-- [0, 0, 1]
-...
-fiber.resume(f)
----
-...
-fiber.resume(f)
----
-- true
-...
-function r() return fiber.yield(fiber.create(r)) end
----
-...
-f = r()
----
-...
-f1 = fiber.resume(f)
----
-...
-f2 = fiber.resume(f1)
----
-...
-f3 = fiber.resume(f2)
----
-...
-f4 = fiber.resume(f3)
----
-...
-f5 = fiber.resume(f4)
----
-...
-f6 = fiber.resume(f5)
----
-...
-f7 = fiber.resume(f6)
----
-...
-f8 = fiber.resume(f7)
----
-...
-f9 = fiber.resume(f8)
----
-...
-f10 = fiber.resume(f9)
----
-...
-f11 = fiber.resume(f10)
----
-...
-f12 = fiber.resume(f11)
----
-...
-f13 = fiber.resume(f12)
----
-...
-f14 = fiber.resume(f13)
----
-...
-f15 = fiber.resume(f14)
----
-...
-f16 = fiber.resume(f15)
----
-...
-f17 = fiber.resume(f16)
----
-...
-fiber.resume(f)
----
-- true
-...
-fiber.resume(f1)
----
-- true
-...
-fiber.resume(f2)
----
-- true
-...
-fiber.resume(f3)
----
-- true
-...
-fiber.resume(f4)
----
-- true
-...
-fiber.resume(f5)
----
-- true
-...
-fiber.resume(f6)
----
-- true
-...
-fiber.resume(f7)
----
-- true
-...
-fiber.resume(f8)
----
-- true
-...
-fiber.resume(f9)
----
-- true
-...
-fiber.resume(f10)
----
-- true
-...
-fiber.resume(f11)
----
-- true
-...
-fiber.resume(f12)
----
-- true
-...
-fiber.resume(f13)
----
-- true
-...
-fiber.resume(f14)
----
-- true
-...
-fiber.resume(f15)
----
-- true
-...
-fiber.resume(f16)
----
-- true
-...
-f17 = nil
----
-...
-function r() fiber.detach() fiber.sleep(1000) end
+-- test fiber.cancel
+function r() fiber.sleep(1000) end
 ---
 ...
 f = fiber.create(r)
 ---
 ...
-fiber.resume(f)
----
-...
-fiber.resume(f)
----
-- error: 'fiber.resume(): can''t resume a detached fiber'
-...
 fiber.cancel(f)
 ---
 ...
-fiber.resume(f)
+f:status()
 ---
-- error: 'fiber.resume(): the fiber is dead'
+- dead
 ...
 --  Test fiber.name()
 old_name = fiber.name()
@@ -792,44 +552,36 @@ dofile("fiber.lua")
 -- print run fiber's test
 box_fiber_run_test()
 ---
-- - 'tester: status(tester) = running'
+- - 'A: odd  1'
   - 'tester: status(printer) = suspended'
   - 'count: 1'
-  - 'printer: tester status = normal'
-  - 'printer: printer status = running'
-  - 'A: odd  1'
   - 'status: suspended'
-  - 'count: 2'
   - 'B: odd  1'
   - 'C: event  2'
+  - 'count: 2'
   - 'status: suspended'
-  - 'count: 3'
   - 'A: odd  3'
+  - 'count: 3'
   - 'status: suspended'
-  - 'count: 4'
   - 'B: odd  3'
   - 'C: event  4'
   - 'D: event  4'
   - 'A: odd  5'
+  - 'count: 4'
   - 'status: suspended'
-  - 'count: 5'
   - 'B: odd  5'
-  - 'status: dead'
 ...
+-- various...
 function testfun() while true do fiber.sleep(10) end end
 ---
 ...
-f = fiber.wrap(testfun)
+f = fiber.create(testfun)
 ---
 ...
 f:cancel()
 ---
 ...
-f:resume()
----
-- error: 'fiber.resume(): the fiber is dead'
-...
-fib_id = fiber.wrap(testfun):id()
+fib_id = fiber.create(testfun):id()
 ---
 ...
 fiber.find(fib_id):cancel()
@@ -839,6 +591,6 @@ fiber.find(fib_id)
 ---
 - null
 ...
-box.fiber = nil
+fiber = nil
 ---
 ...
diff --git a/test/box/fiber.test.lua b/test/box/fiber.test.lua
index 87c8b1a03f..14078a4226 100644
--- a/test/box/fiber.test.lua
+++ b/test/box/fiber.test.lua
@@ -67,7 +67,6 @@ space:truncate()
 
 --# setopt delimiter ';'
 function y()
-    fiber.detach('started')
     space = box.space['tweedledum']
     while true do
         space:replace{1953719668, os.time()}
@@ -75,14 +74,13 @@ function y()
     end
 end;
 f = fiber.create(y);
-fiber.resume(f);
 fiber.sleep(0.002);
 fiber.cancel(f);
-fiber.resume(f);
+-- fiber garbage collection
 for k = 1, 1000, 1 do
     fiber.create(
         function()
-            fiber.detach()
+            fiber.sleep(0)
         end
     )
 end;
@@ -98,39 +96,35 @@ fiber.find('test')
 --  https://github.com/tarantool/tarantool/issues/131
 --  fiber.resume(fiber.cancel()) -- hang
 f = fiber.create(function() fiber.cancel(fiber.self()) end)
-fiber.resume(f)
 f = nil
 -- https://github.com/tarantool/tarantool/issues/119
-ftest = function() fiber.sleep(0.01 * math.random() ) return true end
+ftest = function() fiber.sleep(0.0001 * math.random() ) return true end
 
 --# setopt delimiter ';'
+result = 0;
 for i = 1, 10 do
-    result = {}
+    local res = {}
     for j = 1, 300 do
-        fiber.resume(fiber.create(function()
-            fiber.detach()
-            table.insert(result, ftest())
-        end))
+        fiber.create(function() table.insert(res, ftest()) end)
     end
-    while #result < 300 do fiber.sleep(0.01) end
+    while #res < 300 do fiber.sleep(0) end
+    result = result + #res
 end;
 --# setopt delimiter ''
-#result
-
---# setopt delimiter ''
+result
 --
 -- 
---  Test fiber.wrap()
+--  Test fiber.create()
 -- 
 --  This should try to infinitely create fibers,
 --  but hit the fiber stack size limit and fail
 --  with an error.
-f = function() fiber.wrap(f) end
+f = function() fiber.create(f) end
 f()
 -- 
 -- Test argument passing
 -- 
-f = function(a, b) fiber.wrap(function(arg) result = arg end, a..b) end
+f = function(a, b) fiber.create(function(arg) result = arg end, a..b) end
 f('hello ', 'world')
 result
 f('bye ', 'world')
@@ -138,23 +132,23 @@ result
 -- 
 -- Test that the created fiber is detached
 -- 
-fiber.wrap(function() result = fiber.status() end)
+local f = fiber.create(function() result = fiber.status() end)
 result
 -- A test case for Bug#933487
 -- tarantool crashed during shutdown if non running LUA fiber
 -- was created
-f = fiber.create(function () return true end)
+f = fiber.create(function () fiber.sleep(1) return true end)
 box.snapshot()
 box.snapshot()
 box.snapshot()
-fiber.resume(f)
-f = fiber.create(function () return true end)
-
+f = fiber.create(function () fiber.sleep(1) end)
+-- Test fiber.sleep()
 fiber.sleep(0)
 fiber.sleep(0.01)
 fiber.sleep(0.0001)
 fiber.sleep('hello')
 fiber.sleep(box, 0.001)
+-- test fiber.self()
 fiber.cancel(fiber.self())
 f = fiber.self()
 old_id = f:id()
@@ -164,105 +158,37 @@ fiber.cancel(fiber.self())
 fiber.self():id() - old_id < 5
 g = fiber.self()
 f==g
-function r() f = fiber.create(r) return (fiber.resume(f)) end
-r()
+-- arguments to fiber.create
 f = fiber.create(print('hello'))
-fiber.resume(f)
 -- test passing arguments in and out created fiber
-function r(a, b) return a, b end
+function r(a, b) res = { a, b } end
 f=fiber.create(r)
-fiber.resume(f)
-f=fiber.create(r)
-fiber.resume(f, 'hello')
-f=fiber.create(r)
-fiber.resume(f, 'hello', 'world')
-f=fiber.create(r)
-fiber.resume(f, 'hello', 'world', 'wide')
-function y(a, b) c=fiber.yield(a) return fiber.yield(b, c) end
-f=fiber.create(y)
-fiber.resume(f, 'hello', 'world')
-fiber.resume(f, 'wide')
-fiber.resume(f)
-function y() fiber.detach() while true do box.replace(0, 1953719668, os.time()) fiber.sleep(0.001) end end
-f = fiber.create(y)
-fiber.resume(f)
-fiber.sleep(0.002)
-fiber.cancel(f)
-fiber.resume(f)
-f=nil
-for k=1, 10000, 1 do fiber.create(function() fiber.detach() end) end
+while f:status() == 'running' do fiber.sleep(0) end
+res
+f=fiber.create(r, 'hello')
+while f:status() == 'running' do fiber.sleep(0) end
+res
+f=fiber.create(r, 'hello, world')
+while f:status() == 'running' do fiber.sleep(0) end
+res
+f=fiber.create(r, 'hello', 'world', 'wide')
+while f:status() == 'running' do fiber.sleep(0) end
+res
+for k=1, 10000, 1 do fiber.create(function() fiber.sleep(0) end) end
 collectgarbage('collect')
 -- check that these newly created fibers are garbage collected
 fiber.find(9000)
 fiber.find(9010)
 fiber.find(9020)
-
 --  test fiber.status functions: invalid arguments
 fiber.status(1)
 fiber.status('fafa-gaga')
 fiber.status(nil)
-
---  A test case for Bug#911641 fiber.sleep() works incorrectly if
---  a fiber is attached.
-function r() return fiber.sleep(0.01) end
-f = fiber.create(r)
-fiber.resume(f)
-fiber.resume(f)
---# setopt delimiter ';'
-function r()
-    fiber.yield(box.space.tweedledum:insert{0, 0, 1})
-    fiber.yield(box.space.tweedledum:get{0})
-    fiber.yield(box.space.tweedledum:truncate())
-end;
---# setopt delimiter ''
+-- test fiber.cancel
+function r() fiber.sleep(1000) end
 f = fiber.create(r)
-fiber.resume(f)
-fiber.resume(f)
-fiber.resume(f)
-fiber.resume(f)
-function r() return fiber.yield(fiber.create(r)) end
-f = r()
-f1 = fiber.resume(f)
-f2 = fiber.resume(f1)
-f3 = fiber.resume(f2)
-f4 = fiber.resume(f3)
-f5 = fiber.resume(f4)
-f6 = fiber.resume(f5)
-f7 = fiber.resume(f6)
-f8 = fiber.resume(f7)
-f9 = fiber.resume(f8)
-f10 = fiber.resume(f9)
-f11 = fiber.resume(f10)
-f12 = fiber.resume(f11)
-f13 = fiber.resume(f12)
-f14 = fiber.resume(f13)
-f15 = fiber.resume(f14)
-f16 = fiber.resume(f15)
-f17 = fiber.resume(f16)
-fiber.resume(f)
-fiber.resume(f1)
-fiber.resume(f2)
-fiber.resume(f3)
-fiber.resume(f4)
-fiber.resume(f5)
-fiber.resume(f6)
-fiber.resume(f7)
-fiber.resume(f8)
-fiber.resume(f9)
-fiber.resume(f10)
-fiber.resume(f11)
-fiber.resume(f12)
-fiber.resume(f13)
-fiber.resume(f14)
-fiber.resume(f15)
-fiber.resume(f16)
-f17 = nil
-function r() fiber.detach() fiber.sleep(1000) end
-f = fiber.create(r)
-fiber.resume(f)
-fiber.resume(f)
 fiber.cancel(f)
-fiber.resume(f)
+f:status()
 --  Test fiber.name()
 old_name = fiber.name()
 fiber.name() == old_name
@@ -279,12 +205,11 @@ space:drop()
 dofile("fiber.lua")
 -- print run fiber's test
 box_fiber_run_test()
-
+-- various...
 function testfun() while true do fiber.sleep(10) end end
-f = fiber.wrap(testfun)
+f = fiber.create(testfun)
 f:cancel()
-f:resume()
-fib_id = fiber.wrap(testfun):id()
+fib_id = fiber.create(testfun):id()
 fiber.find(fib_id):cancel()
 fiber.find(fib_id)
-box.fiber = nil
+fiber = nil
diff --git a/test/box/ipc.result b/test/box/ipc.result
index ff17f0048e..9f98fbb22f 100644
--- a/test/box/ipc.result
+++ b/test/box/ipc.result
@@ -56,7 +56,7 @@ buffer = {}
 ---
 ...
 --# setopt delimiter ';'
-tfbr = fiber.wrap(
+tfbr = fiber.create(
     function()
         while true do
             table.insert(buffer, ch:get())
@@ -171,7 +171,7 @@ ch:is_empty()
 - true
 ...
 --# setopt delimiter ';'
-tfbr = fiber.wrap(
+tfbr = fiber.create(
     function()
         while true do
             local v = ch:get()
@@ -181,7 +181,7 @@ tfbr = fiber.wrap(
 );
 ---
 ...
-tfbr2 = fiber.wrap(
+tfbr2 = fiber.create(
     function()
         while true do
             local v = ch:get()
@@ -300,7 +300,7 @@ ch:is_closed()
 passed = false
 ---
 ...
-type(fiber.wrap(function() if ch:get() == nil then passed = true end end))
+type(fiber.create(function() if ch:get() == nil then passed = true end end))
 ---
 - userdata
 ...
@@ -341,7 +341,7 @@ ch:is_closed()
 passed = false
 ---
 ...
-type(fiber.wrap(function() if ch:put(true) == false then passed = true end end))
+type(fiber.create(function() if ch:put(true) == false then passed = true end end))
 ---
 - userdata
 ...
@@ -383,7 +383,7 @@ for i = 1, 10 do table.insert(chs, fiber.channel()) end;
 ---
 ...
 for i = 1, 10 do
-    local no = i fiber.wrap(
+    local no = i fiber.create(
         function()
             fiber.self():name('pusher')
             while true do
@@ -396,7 +396,7 @@ end;
 ---
 ...
 for i = 1, 10 do
-    local no = i fiber.wrap(
+    local no = i fiber.create(
         function()
             fiber.self():name('receiver')
             while true do
diff --git a/test/box/ipc.test.lua b/test/box/ipc.test.lua
index 4f53a2e697..fa2829234c 100644
--- a/test/box/ipc.test.lua
+++ b/test/box/ipc.test.lua
@@ -15,7 +15,7 @@ ch:is_full()
 ch:is_empty()
 buffer = {}
 --# setopt delimiter ';'
-tfbr = fiber.wrap(
+tfbr = fiber.create(
     function()
         while true do
             table.insert(buffer, ch:get())
@@ -48,7 +48,7 @@ ch:get()
 ch:is_full()
 ch:is_empty()
 --# setopt delimiter ';'
-tfbr = fiber.wrap(
+tfbr = fiber.create(
     function()
         while true do
             local v = ch:get()
@@ -56,7 +56,7 @@ tfbr = fiber.wrap(
         end
     end
 );
-tfbr2 = fiber.wrap(
+tfbr2 = fiber.create(
     function()
         while true do
             local v = ch:get()
@@ -85,7 +85,7 @@ buffer
 ch = fiber.channel(1)
 ch:is_closed()
 passed = false
-type(fiber.wrap(function() if ch:get() == nil then passed = true end end))
+type(fiber.create(function() if ch:get() == nil then passed = true end end))
 ch:close()
 passed
 ch:get()
@@ -97,7 +97,7 @@ ch = fiber.channel(1)
 ch:put(true)
 ch:is_closed()
 passed = false
-type(fiber.wrap(function() if ch:put(true) == false then passed = true end end))
+type(fiber.create(function() if ch:put(true) == false then passed = true end end))
 ch:close()
 passed
 ch:get()
@@ -116,7 +116,7 @@ for i = 1, 10 do table.insert(chs, fiber.channel()) end;
 
 
 for i = 1, 10 do
-    local no = i fiber.wrap(
+    local no = i fiber.create(
         function()
             fiber.self():name('pusher')
             while true do
@@ -128,7 +128,7 @@ for i = 1, 10 do
 end;
 
 for i = 1, 10 do
-    local no = i fiber.wrap(
+    local no = i fiber.create(
         function()
             fiber.self():name('receiver')
             while true do
diff --git a/test/box/lua/fiber.lua b/test/box/lua/fiber.lua
index adb53b8ef7..2bc8111f89 100644
--- a/test/box/lua/fiber.lua
+++ b/test/box/lua/fiber.lua
@@ -1,3 +1,4 @@
+local fiber = require('fiber')
 -- -------------------------------------------------------------------------- --
 -- Local functions
 -- -------------------------------------------------------------------------- --
@@ -18,7 +19,7 @@ local result = {}
 -- odd printer
 local function odd(x)
 	table.insert(result,'A: odd  '..tostring(x))
-    fiber.yield(x)
+    fiber.sleep(0.0)
 	table.insert(result,'B: odd  '..tostring(x))
 end
 
@@ -26,18 +27,16 @@ end
 local function even(x)
 	table.insert(result,'C: event  '..tostring(x))
     if x == 2 then
-        return x
+        return
     end
 	table.insert(result,'D: event  '..tostring(x))
 end
 
 -- printer task routine main function
 local function printer_task_routine(x)
-	table.insert(result, "printer: tester status = " .. fiber.status(tester_task))
-	table.insert(result, "printer: printer status = " .. fiber.status(printer_task))
     for i = 1, x do
         if i == 3 then
-            fiber.yield(-1)
+            fiber.sleep(0)
         end
         if i % 2 == 0 then
             even(i)
@@ -48,21 +47,20 @@ local function printer_task_routine(x)
 end
 
 
--- -------------------------------------------------------------------------- --
+------------------------------------------------------------------------
 -- tester task routines
--- -------------------------------------------------------------------------- --
+------------------------------------------------------------------------
 
 -- tester task routine main function
 local function tester_task_routine()
-    printer_task = fiber.create(printer_task_routine)
-	table.insert(result, "tester: status(tester) = " .. fiber.status(tester_task))
-	table.insert(result, "tester: status(printer) = " .. fiber.status(printer_task))
+    printer_task = fiber.create(printer_task_routine, 5)
+	table.insert(result, "tester: status(printer) = " .. printer_task:status())
     count = 1
-    while fiber.status(printer_task) ~= "dead" do
+    while printer_task:status() ~= "dead" do
 		table.insert(result, "count: " .. tostring(count))
-        fiber.resume(printer_task, 5)
-		table.insert(result, "status: " .. fiber.status(printer_task))
+		table.insert(result, "status: " .. printer_task:status())
         count = count + 1
+        fiber.sleep(0)
     end
 end
 
@@ -75,6 +73,8 @@ end
 function box_fiber_run_test()
     -- run tester
     tester_task = fiber.create(tester_task_routine)
-    fiber.resume(tester_task)
+    while tester_task:status() ~= 'dead' do
+        fiber.sleep(0)
+    end
 	return result
 end
diff --git a/test/box/print.result b/test/box/print.result
index e4cdb1491a..6ab6a18f26 100644
--- a/test/box/print.result
+++ b/test/box/print.result
@@ -4,9 +4,8 @@ print("Hello, world")
 io = require('io')
 ---
 ...
-require('fiber').wrap(function() print('Ehllo, world') io.flush() end)
+local f = require('fiber').create(function() print('Ehllo, world') io.flush() end)
 ---
-- null
 ...
 require('fiber').sleep(0.1)
 ---
diff --git a/test/box/print.test.py b/test/box/print.test.py
index 9b0f56f0ec..5dfdd82e54 100644
--- a/test/box/print.test.py
+++ b/test/box/print.test.py
@@ -12,7 +12,7 @@ log = server.logfile
 f = open(log, "r")
 f.seek(0, 2)
 
-admin("require('fiber').wrap(function() print('Ehllo, world') io.flush() end)")
+admin("local f = require('fiber').create(function() print('Ehllo, world') io.flush() end)")
 admin("require('fiber').sleep(0.1)")
 line = f.readline()
 print("Check log line")
diff --git a/test/box/session.result b/test/box/session.result
index 841cc443fd..2c657ed58f 100644
--- a/test/box/session.result
+++ b/test/box/session.result
@@ -31,27 +31,16 @@ session.id() > 0
 ---
 - true
 ...
-f = fiber.create(function() fiber.detach() failed = session.id() == 0 end)
+f = fiber.create(function() failed = session.id() == 0 end)
 ---
 ...
-fiber.resume(f)
+while f:status() ~= 'dead' do fiber.sleep(0) end
 ---
 ...
 failed
 ---
 - false
 ...
-f1 = fiber.create(function() if session.id() == 0 then failed = true end end)
----
-...
-fiber.resume(f1)
----
-- true
-...
-failed
----
-- false
-...
 session.peer() == session.peer(session.id())
 ---
 - true
diff --git a/test/box/session.test.lua b/test/box/session.test.lua
index 62a0435dc8..bbd09b4e04 100644
--- a/test/box/session.test.lua
+++ b/test/box/session.test.lua
@@ -11,11 +11,8 @@ session.exists(1234567890)
 
 -- check session.id()
 session.id() > 0
-f = fiber.create(function() fiber.detach() failed = session.id() == 0 end)
-fiber.resume(f)
-failed
-f1 = fiber.create(function() if session.id() == 0 then failed = true end end)
-fiber.resume(f1)
+f = fiber.create(function() failed = session.id() == 0 end)
+while f:status() ~= 'dead' do fiber.sleep(0) end
 failed
 session.peer() == session.peer(session.id())
 
diff --git a/test/box/socket.result b/test/box/socket.result
index 56b3945ee1..01c87cd3c9 100644
--- a/test/box/socket.result
+++ b/test/box/socket.result
@@ -902,7 +902,7 @@ ping
 s:close()
 ---
 ...
- replies = 0 packet = require('msgpack').encode({[0] = 64, [1] = 0}) packet = require('msgpack').encode(packet:len())..packet function bug1160869()     local s = socket.tcp()     s:connect('127.0.0.1', string.gsub(box.cfg.listen, '^.*:', ''))     s:recv(128)     require('fiber').wrap(function()         while true do             _, status =  s:recv(18)             if status == "eof" then                 error("unexpected eof")             end             replies = replies + 1         end     end)     return s:send(packet) end 
+ replies = 0 packet = require('msgpack').encode({[0] = 64, [1] = 0}) packet = require('msgpack').encode(packet:len())..packet function bug1160869()     local s = socket.tcp()     s:connect('127.0.0.1', string.gsub(box.cfg.listen, '^.*:', ''))     s:recv(128)     require('fiber').create(function()         while true do             _, status =  s:recv(18)             if status == "eof" then                 error("unexpected eof")             end             replies = replies + 1         end     end)     return s:send(packet) end 
 ---
 ...
 bug1160869()
@@ -924,7 +924,7 @@ replies
 ---
 - 3
 ...
- s = nil syncno = 0 reps = 0 packet = require('msgpack').encode({[0] = 64, [1] = 0}) packet = require('msgpack').encode(packet:len())..packet function iostart()     if s ~= nil then         return     end     s = socket.tcp()     s:connect('127.0.0.1', string.gsub(box.cfg.listen, '^.*:', ''))     s:recv(128)     require('fiber').wrap(function()         while true do             s:recv(18)             if status == "eof" then                 error("unexpected eof")             end             reps = reps + 1         end     end) end  function iotest()     iostart()     syncno = syncno + 1     packet = require('msgpack').encode({[0] = 64, [1] = syncno})     packet = require('msgpack').encode(packet:len())..packet     return s:send(packet) end 
+ s = nil syncno = 0 reps = 0 packet = require('msgpack').encode({[0] = 64, [1] = 0}) packet = require('msgpack').encode(packet:len())..packet function iostart()     if s ~= nil then         return     end     s = socket.tcp()     s:connect('127.0.0.1', string.gsub(box.cfg.listen, '^.*:', ''))     s:recv(128)     require('fiber').create(function()         while true do             s:recv(18)             if status == "eof" then                 error("unexpected eof")             end             reps = reps + 1         end     end) end  function iotest()     iostart()     syncno = syncno + 1     packet = require('msgpack').encode({[0] = 64, [1] = syncno})     packet = require('msgpack').encode(packet:len())..packet     return s:send(packet) end 
 ---
 ...
 iotest()
@@ -949,7 +949,7 @@ reps
 test_listen_done = false
 ---
 ...
- function server()     ms = socket.tcp()     ms:bind('127.0.0.1', 8181)     ms:listen()     test_listen_done = true      while true do         local s = ms:accept( .5 )         if s ~= 'timeout' then             print("accepted connection ", s)             s:send('Hello world')             s:shutdown(socket.SHUT_RDWR)         end     end end  fbr = require('fiber').wrap(server) 
+ function server()     ms = socket.tcp()     ms:bind('127.0.0.1', 8181)     ms:listen()     test_listen_done = true      while true do         local s = ms:accept( .5 )         if s ~= 'timeout' then             print("accepted connection ", s)             s:send('Hello world')             s:shutdown(socket.SHUT_RDWR)         end     end end  fbr = require('fiber').create(server) 
 ---
 ...
 wait_cout = 100 while not test_listen_done and wait_cout > 0 do require('fiber').sleep(0.001) wait_cout = wait_cout - 1 end
diff --git a/test/box/socket.test.py b/test/box/socket.test.py
index f9b2b4b043..2085b4b1c4 100644
--- a/test/box/socket.test.py
+++ b/test/box/socket.test.py
@@ -518,7 +518,7 @@ function bug1160869()
     local s = socket.tcp()
     s:connect('127.0.0.1', string.gsub(box.cfg.listen, '^.*:', ''))
     s:recv(128)
-    require('fiber').wrap(function()
+    require('fiber').create(function()
         while true do
             _, status =  s:recv(18)
             if status == "eof" then
@@ -551,7 +551,7 @@ function iostart()
     s = socket.tcp()
     s:connect('127.0.0.1', string.gsub(box.cfg.listen, '^.*:', ''))
     s:recv(128)
-    require('fiber').wrap(function()
+    require('fiber').create(function()
         while true do
             s:recv(18)
             if status == "eof" then
@@ -598,7 +598,7 @@ function server()
     end
 end
 
-fbr = require('fiber').wrap(server)
+fbr = require('fiber').create(server)
 """
 admin("test_listen_done = false")
 admin(test.replace('\n', ' '))
diff --git a/test/box/suite.ini b/test/box/suite.ini
index c4ed54055d..adc25b973e 100644
--- a/test/box/suite.ini
+++ b/test/box/suite.ini
@@ -2,7 +2,7 @@
 core = tarantool
 description = tarantool/box, minimal configuration
 script = box.lua
-disabled = configuration.test.py reconfigure.test.py
+disabled =
 valgrind_disabled = admin_coredump.test.lua
 release_disabled = errinj.test.lua errinj_index.test.lua
 lua_libs = lua/fiber.lua lua/fifo.lua
diff --git a/test/box/transaction.result b/test/box/transaction.result
index c2f2e28ac6..1cf1fa1d15 100644
--- a/test/box/transaction.result
+++ b/test/box/transaction.result
@@ -45,7 +45,7 @@ function sloppy()
 end;
 ---
 ...
-f = fiber.wrap(sloppy);
+f = fiber.create(sloppy);
 ---
 ...
 -- when the sloppy fiber ends, its session has an active transction
diff --git a/test/box/transaction.test.lua b/test/box/transaction.test.lua
index 981430f48d..07260e2f8c 100644
--- a/test/box/transaction.test.lua
+++ b/test/box/transaction.test.lua
@@ -21,7 +21,7 @@ fiber = require('fiber');
 function sloppy()
     box.begin()
 end;
-f = fiber.wrap(sloppy);
+f = fiber.create(sloppy);
 -- when the sloppy fiber ends, its session has an active transction
 -- ensure it's rolled back automatically
 fiber.sleep(0);
-- 
GitLab