Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: tarantool-patches@dev.tarantool.org, gorcunov@gmail.com,
	sergepetrenko@tarantool.org
Subject: [Tarantool-patches] [PATCH 03/16] tuple: pass global ibuf explicitly where possible
Date: Sat, 20 Mar 2021 01:42:40 +0100	[thread overview]
Message-ID: <9dc377c5bb5ecc0b15484541ce8d414e6539fbc4.1616200860.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1616200860.git.v.shpilevoy@tarantool.org>

Code in lua/tuple.c used global tarantool_lua_ibuf in many places
relying on it never being changed and not reused by other code
until a yield.

But it is not so. In fact, as it was discovered in #5632, in any
Lua function may be started GC. Any GC handler might touch some
API also using tarantool_lua_ibuf inside.

This makes the first usage in lua/tuple.c invalid - the buffer
could be reset or reallocated or its wpos/rpos could change during
GC.

In order to fix this, first of all there should be clear points
where the buffer is taken, and where it becomes not needed
anymore.

The patch makes code in lua/tuple.c take tarantool_lua_ibuf when
it is needed first time. Not during usage. The same is done for
the fiber region for the API symmetry.

Part of #5632
---
 src/box/lua/tuple.c | 60 ++++++++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 23 deletions(-)

diff --git a/src/box/lua/tuple.c b/src/box/lua/tuple.c
index 3e6f043b4..ffd01d899 100644
--- a/src/box/lua/tuple.c
+++ b/src/box/lua/tuple.c
@@ -135,10 +135,8 @@ luaT_istuple(struct lua_State *L, int narg)
  * Helper for <lbox_tuple_new>().
  */
 static int
-luaT_tuple_encode_values(struct lua_State *L)
+luaT_tuple_encode_values(struct lua_State *L, struct ibuf *buf)
 {
-	struct ibuf *buf = tarantool_lua_ibuf;
-	ibuf_reset(buf);
 	struct mpstream stream;
 	mpstream_init(&stream, buf, ibuf_reserve_cb, ibuf_alloc_cb, luamp_error,
 		      L);
@@ -151,22 +149,31 @@ luaT_tuple_encode_values(struct lua_State *L)
 	return 0;
 }
 
-typedef void luaT_mpstream_init_f(struct mpstream *stream, struct lua_State *L);
+typedef void luaT_mpstream_init_f(struct mpstream *stream, struct lua_State *L,
+				  void *buffer);
 
 static void
-luaT_mpstream_init_lua_ibuf(struct mpstream *stream, struct lua_State *L)
+luaT_mpstream_init_lua_ibuf(struct mpstream *stream, struct lua_State *L,
+			    void *buffer)
 {
-	mpstream_init(stream, tarantool_lua_ibuf, ibuf_reserve_cb,
+	mpstream_init(stream, (struct ibuf *)buffer, ibuf_reserve_cb,
 		      ibuf_alloc_cb, luamp_error, L);
 }
 
 static void
-luaT_mpstream_init_box_region(struct mpstream *stream, struct lua_State *L)
+luaT_mpstream_init_box_region(struct mpstream *stream, struct lua_State *L,
+			      void *buffer)
 {
-	mpstream_init(stream, &fiber()->gc, region_reserve_cb, region_alloc_cb,
-		      luamp_error, L);
+	mpstream_init(stream, (struct region *)buffer, region_reserve_cb,
+		      region_alloc_cb, luamp_error, L);
 }
 
+/** Helper to pass parameters into luaT_tuple_encode_table via the Lua stack. */
+struct luaT_tuple_encode_ctx {
+	luaT_mpstream_init_f *mpstream_init_f;
+	void *buffer;
+};
+
 /**
  * Encode a Lua table or a tuple as MsgPack.
  *
@@ -178,8 +185,8 @@ static int
 luaT_tuple_encode_table(struct lua_State *L)
 {
 	struct mpstream stream;
-	luaT_mpstream_init_f *luaT_mpstream_init_f = lua_topointer(L, 1);
-	luaT_mpstream_init_f(&stream, L);
+	const struct luaT_tuple_encode_ctx *ctx = lua_topointer(L, 1);
+	ctx->mpstream_init_f(&stream, L, ctx->buffer);
 	luamp_encode_tuple(L, &tuple_serializer, &stream, 2);
 	mpstream_flush(&stream);
 	return 0;
@@ -190,7 +197,8 @@ luaT_tuple_encode_table(struct lua_State *L)
  */
 static int
 luaT_tuple_encode_on_mpstream(struct lua_State *L, int idx,
-			      luaT_mpstream_init_f *luaT_mpstream_init_f)
+			      luaT_mpstream_init_f *luaT_mpstream_init_f,
+			      void *buffer)
 {
 	assert(idx != 0);
 	if (!lua_istable(L, idx) && !luaT_istuple(L, idx)) {
@@ -213,7 +221,11 @@ luaT_tuple_encode_on_mpstream(struct lua_State *L, int idx,
 	lua_rawgeti(L, LUA_REGISTRYINDEX, luaT_tuple_encode_table_ref);
 	assert(lua_isfunction(L, -1));
 
-	lua_pushlightuserdata(L, luaT_mpstream_init_f);
+	struct luaT_tuple_encode_ctx ctx = {
+		.mpstream_init_f = luaT_mpstream_init_f,
+		.buffer = buffer,
+	};
+	lua_pushlightuserdata(L, &ctx);
 	lua_pushvalue(L, idx);
 
 	int rc = luaT_call(L, 2, 0);
@@ -226,12 +238,11 @@ luaT_tuple_encode_on_mpstream(struct lua_State *L, int idx,
  */
 static char *
 luaT_tuple_encode_on_lua_ibuf(struct lua_State *L, int idx,
-			      size_t *tuple_len_ptr)
+			      size_t *tuple_len_ptr, struct ibuf *buf)
 {
-	struct ibuf *buf = tarantool_lua_ibuf;
-	ibuf_reset(buf);
 	if (luaT_tuple_encode_on_mpstream(L, idx,
-					  luaT_mpstream_init_lua_ibuf) != 0)
+					  luaT_mpstream_init_lua_ibuf,
+					  buf) != 0)
 		return NULL;
 	if (tuple_len_ptr != NULL)
 		*tuple_len_ptr = ibuf_used(buf);
@@ -247,7 +258,8 @@ luaT_tuple_encode(struct lua_State *L, int idx, size_t *tuple_len_ptr)
 	struct region *region = &fiber()->gc;
 	size_t region_svp = region_used(region);
 	if (luaT_tuple_encode_on_mpstream(L, idx,
-					  luaT_mpstream_init_box_region) != 0) {
+					  luaT_mpstream_init_box_region,
+					  region) != 0) {
 		region_truncate(region, region_svp);
 		return NULL;
 	}
@@ -268,15 +280,16 @@ luaT_tuple_encode(struct lua_State *L, int idx, size_t *tuple_len_ptr)
 box_tuple_t *
 luaT_tuple_new(struct lua_State *L, int idx, box_tuple_format_t *format)
 {
+	struct ibuf *ibuf = tarantool_lua_ibuf;
+	ibuf_reset(ibuf);
 	size_t tuple_len;
-	char *tuple_data = luaT_tuple_encode_on_lua_ibuf(L, idx, &tuple_len);
+	char *tuple_data = luaT_tuple_encode_on_lua_ibuf(L, idx, &tuple_len,
+							 ibuf);
 	if (tuple_data == NULL)
 		return NULL;
 	box_tuple_t *tuple = box_tuple_new(format, tuple_data,
 					   tuple_data + tuple_len);
-	if (tuple == NULL)
-		return NULL;
-	ibuf_reinit(tarantool_lua_ibuf);
+	ibuf_reinit(ibuf);
 	return tuple;
 }
 
@@ -296,7 +309,8 @@ lbox_tuple_new(lua_State *L)
 	box_tuple_format_t *fmt = box_tuple_format_default();
 	if (argc != 1 || (!lua_istable(L, 1) && !luaT_istuple(L, 1))) {
 		struct ibuf *buf = tarantool_lua_ibuf;
-		luaT_tuple_encode_values(L); /* may raise */
+		ibuf_reset(buf);
+		luaT_tuple_encode_values(L, buf); /* may raise */
 		struct tuple *tuple = box_tuple_new(fmt, buf->buf,
 						    buf->buf + ibuf_used(buf));
 		ibuf_reinit(buf);
-- 
2.24.3 (Apple Git-128)


  parent reply	other threads:[~2021-03-20  0:47 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-20  0:42 [Tarantool-patches] [PATCH 00/16] Cord buffer, static alloc, and Lua GC bug Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 01/16] fio: don't use shared buffer in pread() Vladislav Shpilevoy via Tarantool-patches
2021-03-22  7:19   ` Cyrill Gorcunov via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 10/16] uri: replace static_alloc with ffi stash and ibuf Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 11/16] buffer: remove static_alloc() from Lua Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 12/16] lua: use lua_pushfstring() instead of tt_sprintf() Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 13/16] sio: rework sio_strfaddr() Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 14/16] sio: increase SERVICE_NAME_MAXLEN size Vladislav Shpilevoy via Tarantool-patches
2021-03-21 21:58   ` Cyrill Gorcunov via Tarantool-patches
2021-03-22 22:32     ` Vladislav Shpilevoy via Tarantool-patches
2021-03-23  6:56       ` Cyrill Gorcunov via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 15/16] sio: introduce and use sio_snprintf() Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 16/16] buffer: remove Lua registers Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 02/16] test: don't use IBUF_SHARED in the tests Vladislav Shpilevoy via Tarantool-patches
2021-03-22  7:35   ` Cyrill Gorcunov via Tarantool-patches
2021-03-20  0:42 ` Vladislav Shpilevoy via Tarantool-patches [this message]
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 04/16] iconv: take errno before reseting the context Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 05/16] cord_buf: introduce cord_buf API Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 06/16] cord_buf: introduce ownership management Vladislav Shpilevoy via Tarantool-patches
2021-03-22 16:48   ` Serge Petrenko via Tarantool-patches
2021-03-22 22:32     ` Vladislav Shpilevoy via Tarantool-patches
2021-03-23  7:46       ` Serge Petrenko via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 07/16] buffer: implement ffi stash Vladislav Shpilevoy via Tarantool-patches
2021-03-23  0:29   ` Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 08/16] uuid: replace static_alloc with " Vladislav Shpilevoy via Tarantool-patches
2021-03-20  0:42 ` [Tarantool-patches] [PATCH 09/16] uuid: drop tt_uuid_str() from Lua Vladislav Shpilevoy via Tarantool-patches
2021-03-21 16:38 ` [Tarantool-patches] [PATCH 00/16] Cord buffer, static alloc, and Lua GC bug Vladislav Shpilevoy via Tarantool-patches
2021-03-22  7:52 ` Cyrill Gorcunov via Tarantool-patches
2021-03-22  7:56 ` Konstantin Osipov via Tarantool-patches
2021-03-22 17:17 ` Serge Petrenko via Tarantool-patches
2021-03-23 23:45 ` Vladislav Shpilevoy via Tarantool-patches
2021-03-24 13:28 ` Kirill Yukhin via Tarantool-patches

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=9dc377c5bb5ecc0b15484541ce8d414e6539fbc4.1616200860.git.v.shpilevoy@tarantool.org \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=gorcunov@gmail.com \
    --cc=sergepetrenko@tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH 03/16] tuple: pass global ibuf explicitly where possible' \
    /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