From: Igor Munkin <imun@tarantool.org>
To: Sergey Ostanevich <sergos@tarantool.org>,
Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Cc: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH] fiber: abort trace recording on fiber yield
Date: Tue, 31 Mar 2020 01:44:31 +0300 [thread overview]
Message-ID: <b77be75a94623c0b430875ec1ad292579f86a613.1585606573.git.imun@tarantool.org> (raw)
Since Tarantool fibers doesn't respect Lua coroutine switch mechanism,
JIT machinery stays unnotified when one lua_State substitues another
one. As a result if trace recording hasn't been aborted prior to fiber
switch, the recording proceeds using the new lua_State and leads to
failure either on any compiler phase or on execution the compiled trace.
This changeset adds a mandatory on_yield trigger aborting trace
recording when fiber switches to another one.
Fixes #4491
Closes #1700
Signed-off-by: Igor Munkin <imun@tarantool.org>
---
This patch is based on the changes introduced within [1].
Branch: https://github.com/tarantool/tarantool/tree/imun/gh-1700-abort-recording-on-fiber-switch
Issue:
* https://github.com/tarantool/tarantool/issues/1700
* https://github.com/tarantool/tarantool/issues/4491
[1]: https://lists.tarantool.org/pipermail/tarantool-patches/2020-March/015212.html
src/lua/fiber.c | 39 +++++++++++++-
...-4491-coio-wait-leads-to-segfault.test.lua | 53 +++++++++++++++++++
2 files changed, 90 insertions(+), 2 deletions(-)
create mode 100755 test/app-tap/gh-4491-coio-wait-leads-to-segfault.test.lua
diff --git a/src/lua/fiber.c b/src/lua/fiber.c
index 45bc03787..c79aa7c2b 100644
--- a/src/lua/fiber.c
+++ b/src/lua/fiber.c
@@ -38,6 +38,7 @@
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
+#include <luajit.h>
void
luaL_testcancel(struct lua_State *L)
@@ -454,6 +455,25 @@ lua_fiber_run_f(MAYBE_UNUSED va_list ap)
return result;
}
+static int
+fiber_on_yield(struct trigger *trigger, void *event)
+{
+ (void) trigger;
+ (void) event;
+
+ /*
+ * XXX: According to LuaJIT API reference luaJIT_setmode
+ * function returns 0 on failure and 1 on success. Since
+ * this call is aimed to abort the trace recording on
+ * fiber_yield call and prevent already compiled traces
+ * execution, the mode parameter is an invalid value (-1)
+ * so JIT mode change is expected to fail and 0 is
+ * returned. Otherwise non-zero return value signals
+ * trigger_run routine about this trigger failure.
+ */
+ return luaJIT_setmode(tarantool_L, 0, -1);
+}
+
/**
* Utility function for fiber.create and fiber.new
*/
@@ -467,10 +487,18 @@ fiber_create(struct lua_State *L)
struct fiber *f = fiber_new("lua", lua_fiber_run_f);
if (f == NULL) {
- luaL_unref(L, LUA_REGISTRYINDEX, coro_ref);
- luaT_error(L);
+ /* diagnostics is set in fiber_new. */
+ goto error;
}
+ struct trigger *t = malloc(sizeof(*t));
+ if (t == NULL) {
+ diag_set(OutOfMemory, sizeof(*t), "malloc", "t");
+ goto error;
+ }
+ trigger_create(t, fiber_on_yield, NULL, (trigger_f0) free);
+ trigger_add(&f->on_yield, t);
+
/* Move the arguments to the new coro */
lua_xmove(L, child_L, lua_gettop(L));
/* XXX: 'fiber' is leaked if this throws a Lua error. */
@@ -483,6 +511,13 @@ fiber_create(struct lua_State *L)
lua_pushinteger(child_L, coro_ref);
f->storage.lua.stack = child_L;
return f;
+
+error:
+ /* Release the anchored coroutine. */
+ luaL_unref(L, LUA_REGISTRYINDEX, coro_ref);
+ luaT_error(L);
+ unreachable();
+ return NULL;
}
/**
diff --git a/test/app-tap/gh-4491-coio-wait-leads-to-segfault.test.lua b/test/app-tap/gh-4491-coio-wait-leads-to-segfault.test.lua
new file mode 100755
index 000000000..0dd8dfbee
--- /dev/null
+++ b/test/app-tap/gh-4491-coio-wait-leads-to-segfault.test.lua
@@ -0,0 +1,53 @@
+#!/usr/bin/env tarantool
+
+local tap = require('tap')
+
+local test = tap.test('gh-4491-coio-wait-leads-to-segfault')
+
+-- Test file to demonstrate platform failure due to fiber switch
+-- while trace recording, details:
+-- https://github.com/tarantool/tarantool/issues/4491
+
+local fiber = require('fiber')
+local ffi = require('ffi')
+ffi.cdef('int coio_wait(int fd, int event, double timeout);')
+
+local cfg = {
+ hotloop = arg[1] or 1,
+ fibers = arg[1] or 2,
+ timeout = { put = 1, get = 1 },
+}
+
+test:plan(cfg.fibers + 1)
+
+local args = {
+ fd = 1 , -- STDIN file descriptor
+ event = 0x1 , -- COIO_READ event
+ timeout = 0.05, -- Timeout value
+}
+
+local function run(iterations, channel)
+ for _ = 1, iterations do
+ ffi.C.coio_wait(args.fd, args.event, args.timeout)
+ end
+ channel:put(true, cfg.timeout.put)
+end
+
+local channels = { }
+
+jit.opt.start('3', string.format('hotloop=%d', cfg.hotloop))
+
+for _ = 1, cfg.fibers do
+ channels[_] = fiber.channel(1)
+ fiber.new(run, cfg.hotloop + 1, channels[_])
+end
+
+-- Finalize the existing fibers
+for _ = 1, cfg.fibers do
+ test:ok(channels[_]:get(cfg.timeout.get),
+ string.format('fiber #%d successfully finished', _))
+end
+
+test:ok(true, 'trace is not recorded due to fiber switch underneath coio_wait')
+
+os.exit(test:check() and 0 or 1)
--
2.25.0
next reply other threads:[~2020-03-30 22:50 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-30 22:44 Igor Munkin [this message]
2020-03-31 16:58 ` Konstantin Osipov
2020-03-31 23:57 ` Vladislav Shpilevoy
2020-07-07 22:24 ` Igor Munkin
2020-07-10 10:26 ` sergos
2020-09-21 19:23 ` Igor Munkin
2020-09-21 20:14 ` Sergey Ostanevich
2020-07-11 20:28 ` Vladislav Shpilevoy
2020-09-07 20:35 ` Igor Munkin
2020-09-17 14:21 ` Vladislav Shpilevoy
2020-09-19 15:29 ` Igor Munkin
2020-09-21 20:31 ` Vladislav Shpilevoy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b77be75a94623c0b430875ec1ad292579f86a613.1585606573.git.imun@tarantool.org \
--to=imun@tarantool.org \
--cc=sergos@tarantool.org \
--cc=tarantool-patches@dev.tarantool.org \
--cc=v.shpilevoy@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH] fiber: abort trace recording on fiber yield' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox