From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 4B67D6EC55; Thu, 26 Aug 2021 09:14:28 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 4B67D6EC55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1629958468; bh=Oq4HPKQ3e0LguntqSv6CMzoUa29ymaaeI6XGXJ5dkmY=; h=To:Cc:References:Date:In-Reply-To:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=s576wyHyldFx5S4Fhv9jay0saxA41n22Wns8Laf8tkK2kvg8tebcny8EIrOMGhG55 AOxVie60J9HfPUVAt3K/L/U8xyjIi+CVC+QHl9s/ul2X7RVZ9WKXsr8E6SYMyUTj+9 DwZrG2mxgXa89rW6sgiIIQDxeU+LEUHNnwh7iA7M= Received: from smtp45.i.mail.ru (smtp45.i.mail.ru [94.100.177.105]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 336566EC55 for ; Thu, 26 Aug 2021 09:14:26 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 336566EC55 Received: by smtp45.i.mail.ru with esmtpa (envelope-from ) id 1mJ8ef-0004xP-6G; Thu, 26 Aug 2021 09:14:25 +0300 To: Vladislav Shpilevoy , imun@tarantool.org Cc: tarantool-patches@dev.tarantool.org References: <3453bc40af586cf4242863f1307f72fe5c5a408a.1628713520.git.babinoleg@mail.ru> Message-ID: <275140cf-69d8-8eaf-5da1-220b72009d97@tarantool.org> Date: Thu, 26 Aug 2021 09:14:24 +0300 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-GB X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD92087353F0EC44DD91BCCB18F2C129F87F36E61E9E4584E9D182A05F538085040B1B0868FADEBEC070E387E998C5DB510887FD1654498771858C9F6AB9C81EA85 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7CF4D16325FBE1EEDEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637FAFFEDEAEB71C4328638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D813E902F0F3329E8420F74FD7683A2D34117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCF1175FABE1C0F9B6A471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F446042972877693876707352033AC447995A7AD18C26CFBAC0749D213D2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE140C956E756FBB7AC766E17BBE5724E9D8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE30CABCCA60F52D7EB302FCEF25BFAB345C4224003CC836476EA7A3FFF5B025636E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F7900637FB177F6A8366F17BEFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-C1DE0DAB: 0D63561A33F958A5C9EEAB5C343A5792020BDF3D9408AD65401C3F3DE5C3155AD59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA753177526CD55AFC11410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D348F343DA43F62289F62AAB91ADF566984D9845B463D7D1032E72FD296EA544E65CBC9C542A1282D5D1D7E09C32AA3244C8B64B1BC0471FA6A284CB0656CE3A45630363D8B7DA7DD44FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojXSF/Tsl6M2P7LQFZBK6i0g== X-Mailru-Sender: 583F1D7ACE8F49BD1042885CEC987B6B5DA86B3A55C3282A0E387E998C5DB5105AB84C59671071107019711D9D5B048E1458020726E2BC9FD5ECBA0B92C0A936CDC7563AA7CEBD287402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH 3/4] fiber: keep reference to userdata if fiber created once X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Oleg Babin via Tarantool-patches Reply-To: Oleg Babin Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Thanks for your review. My answers below. On 25.08.2021 23:33, Vladislav Shpilevoy wrote: > Hi! Thanks for the patch! > > See 5 comments below. > >> diff --git a/src/lua/fiber.c b/src/lua/fiber.c >> index 5575f2079..268ddf9cc 100644 >> --- a/src/lua/fiber.c >> +++ b/src/lua/fiber.c >> @@ -87,27 +87,31 @@ luaL_testcancel(struct lua_State *L) >> static const char *fiberlib_name = "fiber"; >> >> /** >> - * @pre: stack top contains a table >> - * @post: sets table field specified by name of the table on top >> - * of the stack to a weak kv table and pops that weak table. >> + * Trigger invoked when the fiber has stopped execution of its >> + * current request. Only purpose - delete storage.lua.ref and >> + * storage.lua.storage_ref keeping a reference of Lua >> + * fiber and fiber.storage objects. Unlike Lua stack, >> + * Lua fiber storage may be created not only for fibers born from >> + * Lua land. For example, an IProto request may execute a Lua >> + * function, which can create the storage. Trigger guarantees, >> + * that even for non-Lua fibers the Lua storage is destroyed. >> */ >> -static void >> -lbox_create_weak_table(struct lua_State *L, const char *name) >> +static int >> +lbox_fiber_on_stop(struct trigger *trigger, void *event) >> { >> - lua_newtable(L); >> - /* and a metatable */ >> - lua_newtable(L); >> - /* weak keys and values */ >> - lua_pushstring(L, "kv"); >> - /* pops 'kv' */ >> - lua_setfield(L, -2, "__mode"); >> - /* pops the metatable */ >> - lua_setmetatable(L, -2); >> - /* assigns and pops table */ >> - lua_setfield(L, -2, name); >> - /* gets memoize back. */ >> - lua_getfield(L, -1, name); >> - assert(! lua_isnil(L, -1)); >> + struct fiber *f = (struct fiber *) event; > 1. In new code we do not use whitespaces after unary operators, > including type casts. But here you don't need a cast. void * is > implicitly compatible with any other pointer type in C. Fixed >> + int storage_ref = f->storage.lua.storage_ref; >> + if (storage_ref > 0) { >> + luaL_unref(tarantool_L, LUA_REGISTRYINDEX, storage_ref); >> + f->storage.lua.storage_ref = LUA_NOREF; >> + } >> + int ref = f->storage.lua.ref; >> + assert(ref > 0); >> + luaL_unref(tarantool_L, LUA_REGISTRYINDEX, ref); >> + f->storage.lua.ref = LUA_NOREF; >> + trigger_clear(trigger); >> + free(trigger); >> + return 0; >> } >> >> /** >> @@ -116,42 +120,26 @@ lbox_create_weak_table(struct lua_State *L, const char *name) >> static void >> lbox_pushfiber(struct lua_State *L, struct fiber *f) >> { >> - /* >> - * Use 'memoize' pattern and keep a single userdata for >> - * the given fiber. This is important to not run __gc >> - * twice for a copy of an attached fiber -- __gc should >> - * not remove attached fiber's coro prematurely. >> - */ >> - luaL_getmetatable(L, fiberlib_name); >> - lua_getfield(L, -1, "memoize"); >> - if (lua_isnil(L, -1)) { >> - /* first access - instantiate memoize */ >> - /* pop the nil */ >> - lua_pop(L, 1); >> - /* create memoize table */ >> - lbox_create_weak_table(L, "memoize"); >> - } >> - /* Find out whether the fiber is already in the memoize table. */ >> - uint64_t fid = f->fid; >> - luaL_pushuint64(L, fid); >> - lua_gettable(L, -2); >> - if (lua_isnil(L, -1)) { >> - /* no userdata for fiber created so far */ >> - /* pop the nil */ >> - lua_pop(L, 1); >> - /* push the key back */ >> - luaL_pushuint64(L, fid); >> + int ref = f->storage.lua.ref; >> + if (ref <= 0) { >> + struct trigger *t = (struct trigger *)malloc(sizeof(*t)); > 2. No need to cast, in C it works as is. Fixed. >> + if (t == NULL) { >> + diag_set(OutOfMemory, sizeof(*t), "malloc", "t"); >> + luaT_error(L); >> + } >> + trigger_create(t, lbox_fiber_on_stop, NULL, (trigger_f0) free); > 3. Should not be a whitespace after the cast. Fixed. >> + trigger_add(&f->on_stop, t); >> + >> + uint64_t fid = f->fid; >> /* create a new userdata */ >> uint64_t *ptr = lua_newuserdata(L, sizeof(*ptr)); >> *ptr = fid; > 4. Did you consider pushing the fiber's pointer instead of its ID? > And keep the fiber struct from deletion until it has no refs in > Lua anymore. That would eliminate lookup in fiber hash on each attempt > to access it. Also might make it simpler to return stuff like fiber.csw > in Lua. I remember there was a problem with the fiber being deleted by > the time you try to access its members. This would solve it. I'll think about it. I guess it's possible but it's required more time and could be done on the top of this patch. >> luaL_getmetatable(L, fiberlib_name); >> lua_setmetatable(L, -2); >> - /* memoize it */ >> - lua_settable(L, -3); >> - luaL_pushuint64(L, fid); >> - /* get it back */ >> - lua_gettable(L, -2); >> + ref = luaL_ref(L, LUA_REGISTRYINDEX); >> + f->storage.lua.ref = ref; >> } >> + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); >> } >> @@ -703,8 +669,6 @@ lbox_fiber_storage(struct lua_State *L) >> diag_set(OutOfMemory, sizeof(*t), "malloc", "t"); >> return luaT_error(L); >> } >> - trigger_create(t, lbox_fiber_on_stop, NULL, (trigger_f0) free); > 5. The trigger 't' now is not used and leaks. Oh, I've missed it. Malloc is removed. >> - trigger_add(&f->on_stop, t); >> lua_newtable(L); /* create local storage on demand */ >> storage_ref = luaL_ref(L, LUA_REGISTRYINDEX); >> f->storage.lua.storage_ref = storage_ref; >> Diff: diff --git a/src/lua/fiber.c b/src/lua/fiber.c index 268ddf9cc..83a6b4850 100644 --- a/src/lua/fiber.c +++ b/src/lua/fiber.c @@ -99,7 +99,7 @@ static const char *fiberlib_name = "fiber";  static int  lbox_fiber_on_stop(struct trigger *trigger, void *event)  { -    struct fiber *f = (struct fiber *) event; +    struct fiber *f = event;      int storage_ref = f->storage.lua.storage_ref;      if (storage_ref > 0) {          luaL_unref(tarantool_L, LUA_REGISTRYINDEX, storage_ref); @@ -122,12 +122,12 @@ lbox_pushfiber(struct lua_State *L, struct fiber *f)  {      int ref = f->storage.lua.ref;      if (ref <= 0) { -        struct trigger *t = (struct trigger *)malloc(sizeof(*t)); +        struct trigger *t = malloc(sizeof(*t));          if (t == NULL) {              diag_set(OutOfMemory, sizeof(*t), "malloc", "t");              luaT_error(L);          } -        trigger_create(t, lbox_fiber_on_stop, NULL, (trigger_f0) free); +        trigger_create(t, lbox_fiber_on_stop, NULL, (trigger_f0)free);          trigger_add(&f->on_stop, t);          uint64_t fid = f->fid; @@ -663,12 +663,6 @@ lbox_fiber_storage(struct lua_State *L)      struct fiber *f = lbox_checkfiber(L, 1);      int storage_ref = f->storage.lua.storage_ref;      if (storage_ref <= 0) { -        struct trigger *t = (struct trigger *) -            malloc(sizeof(*t)); -        if (t == NULL) { -            diag_set(OutOfMemory, sizeof(*t), "malloc", "t"); -            return luaT_error(L); -        }          lua_newtable(L); /* create local storage on demand */          storage_ref = luaL_ref(L, LUA_REGISTRYINDEX);          f->storage.lua.storage_ref = storage_ref;