From 421b9086790d2168640df7e0961f4c62870541fb Mon Sep 17 00:00:00 2001 From: Nikolay Shirokovskiy <nshirokovskiy@tarantool.org> Date: Thu, 11 Jul 2024 11:18:56 +0300 Subject: [PATCH] core: introduce managed system fibers Such fibers are cancelled during Tarantool shutdown the same way as cancelled client fibers. This is internal API. Part of #9722 NO_CHANGELOG=internal NO_DOC=internal --- src/lib/core/fiber.c | 8 ++++++++ src/lib/core/fiber.h | 13 +++++++++++++ src/lua/fiber.c | 15 +++++++++++++++ src/lua/fiber.lua | 3 +++ test/unit/fiber.cc | 6 ++++++ 5 files changed, 45 insertions(+) diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c index d133ddcccb..ba07156163 100644 --- a/src/lib/core/fiber.c +++ b/src/lib/core/fiber.c @@ -2357,6 +2357,12 @@ fiber_set_system(struct fiber *f, bool yesno) } } +void +fiber_set_managed_shutdown(struct fiber *f) +{ + f->flags |= FIBER_MANAGED_SHUTDOWN; +} + int fiber_shutdown(double timeout) { @@ -2364,6 +2370,8 @@ fiber_shutdown(double timeout) cord()->is_shutdown = true; struct fiber *fiber; rlist_foreach_entry(fiber, &cord()->alive, link) { + if (fiber->flags & FIBER_MANAGED_SHUTDOWN) + fiber_set_system(fiber, false); if (!(fiber->flags & FIBER_IS_SYSTEM)) fiber_cancel(fiber); } diff --git a/src/lib/core/fiber.h b/src/lib/core/fiber.h index 2f0885ba60..4abdb92847 100644 --- a/src/lib/core/fiber.h +++ b/src/lib/core/fiber.h @@ -175,6 +175,11 @@ enum { * once again nor can its joinability be changed. */ FIBER_JOIN_BEEN_INVOKED = 1 << 9, + /** + * Makes sense only for system fibers. If flag is set then fiber + * will be finished on fiber_shutdown(). + */ + FIBER_MANAGED_SHUTDOWN = 1 << 10, FIBER_DEFAULT_FLAGS = 0 }; @@ -1245,6 +1250,14 @@ fiber_lua_state(struct fiber *f); void fiber_set_system(struct fiber *f, bool yesno); +/** + * Turn managed shutdown on for system fiber. See FIBER_MANAGED_SHUTDOWN. + * It is should be used after fiber creation. Using it during shutdown does not + * work. + */ +void +fiber_set_managed_shutdown(struct fiber *f); + /** * Cancel all client (non system) fibers and wait until they finished. * diff --git a/src/lua/fiber.c b/src/lua/fiber.c index 88ea0fad35..d66f59d314 100644 --- a/src/lua/fiber.c +++ b/src/lua/fiber.c @@ -938,6 +938,20 @@ lbox_fiber_set_system(struct lua_State *L) return 0; } +/** Turn managed shutdown for fiber. Takes the fiber as single argument. */ +static int +lbox_fiber_set_managed_shutdown(struct lua_State *L) +{ + if (lua_gettop(L) != 1) { + diag_set(IllegalParams, + "fiber.set_managed_shutdown(id): bad arguments"); + luaT_error(L); + } + struct fiber *fiber = lbox_checkfiber(L, 1); + fiber_set_managed_shutdown(fiber); + return 0; +} + /** Helper for fiber slice parsing. */ static struct fiber_slice lbox_fiber_slice_parse(struct lua_State *L, int idx) @@ -1085,6 +1099,7 @@ static const struct luaL_Reg fiberlib[] = { /* Internal functions, to hide in fiber.lua. */ {"stall", lbox_fiber_stall}, {"set_system", lbox_fiber_set_system}, + {"set_managed_shutdown", lbox_fiber_set_managed_shutdown}, {NULL, NULL} }; diff --git a/src/lua/fiber.lua b/src/lua/fiber.lua index 48eda368ad..44470e8043 100644 --- a/src/lua/fiber.lua +++ b/src/lua/fiber.lua @@ -74,8 +74,10 @@ fiber.clock64 = fiber_clock64 local stall = fiber.stall local fiber_set_system = fiber.set_system +local fiber_set_managed_shutdown = fiber.set_managed_shutdown fiber.stall = nil fiber.set_system = nil +fiber.set_managed_shutdown = nil local worker_next_task = nil local worker_last_task @@ -134,6 +136,7 @@ end fiber._internal = fiber._internal or {} fiber._internal.schedule_task = worker_schedule_task fiber._internal.set_system = fiber_set_system +fiber._internal.set_managed_shutdown = fiber_set_managed_shutdown setmetatable(fiber, {__serialize = function(self) local res = table.copy(self) diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc index 36cd59b742..5daf597529 100644 --- a/test/unit/fiber.cc +++ b/test/unit/fiber.cc @@ -695,6 +695,10 @@ fiber_test_shutdown(void) struct fiber *fiber4 = fiber_new("fiber4", new_fiber_on_shudown_f); fail_unless(fiber4 != NULL); fiber_set_joinable(fiber4, true); + struct fiber *fiber6 = fiber_new_system("fiber6", wait_cancel_f); + fail_unless(fiber6 != NULL); + fiber_set_managed_shutdown(fiber6); + fiber_set_joinable(fiber6, true); int rc = fiber_shutdown(1000.0); fail_unless(rc == 0); @@ -703,9 +707,11 @@ fiber_test_shutdown(void) fail_unless((fiber2->flags & FIBER_IS_DEAD) == 0); fail_unless((fiber3->flags & FIBER_IS_DEAD) == 0); fail_unless((fiber4->flags & FIBER_IS_DEAD) != 0); + fail_unless((fiber6->flags & FIBER_IS_DEAD) != 0); fiber_join(fiber1); fiber_join(fiber4); + fiber_join(fiber6); fiber_set_joinable(fiber2, true); fiber_cancel(fiber2); -- GitLab