diff --git a/changelogs/unreleased/gh-5843-fiber-wakeup.md b/changelogs/unreleased/gh-5843-fiber-wakeup.md new file mode 100644 index 0000000000000000000000000000000000000000..f501bc04f2467fecfd6be162d63e9fcb07d828d5 --- /dev/null +++ b/changelogs/unreleased/gh-5843-fiber-wakeup.md @@ -0,0 +1,6 @@ +## bugfix/core + +* Remove assertion raised in case of `fiber_wakeup()` get called with + dead fibers. Due to backward compatibility we've allowed such calls + for release builds but not for debug builds. In result there + was inconsistency between program behaviour (gh-5843). diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c index 87a18a6a50d02be6fb8994a5b4ef201fca7281b5..bc9a649dfd7ac2ece1c62ba6ede99c94f019875a 100644 --- a/src/lib/core/fiber.c +++ b/src/lib/core/fiber.c @@ -502,14 +502,15 @@ void fiber_wakeup(struct fiber *f) { /* - * DEAD is checked both in the assertion and in the release build - * because it should not ever happen, at least internally. But in some - * user modules it might happen, and better ignore such fibers. - * Especially since this was allowed for quite some time in the public - * API and need to keep it if it costs nothing, for backward - * compatibility. + * DEAD fiber can be lingering in the cord fiber list + * if it is joinable. And once its execution is complete + * it should be reaped with fiber_join() call. + * + * Still our API allows to call fiber_wakeup() on dead + * joinable fibers so simply ignore it. */ - assert((f->flags & FIBER_IS_DEAD) == 0); + assert((f->flags & FIBER_IS_DEAD) == 0 || + (f->flags & FIBER_IS_JOINABLE) != 0); const int no_flags = FIBER_IS_READY | FIBER_IS_DEAD | FIBER_IS_RUNNING; if ((f->flags & no_flags) == 0) fiber_make_ready(f); diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc index eb0637f85845bd059ec29774ee73ede69f050cea..09ef30cf1e985207994375259a24f4a8b4001cec 100644 --- a/test/unit/fiber.cc +++ b/test/unit/fiber.cc @@ -276,6 +276,21 @@ fiber_wakeup_self_test() footer(); } +static void +fiber_wakeup_dead_test() +{ + header(); + + struct fiber *fiber = fiber_new_xc("wakeup_dead", noop_f); + fiber_set_joinable(fiber, true); + fiber_start(fiber); + fiber_wakeup(fiber); + fiber_wakeup(fiber); + fiber_join(fiber); + + footer(); +} + static void fiber_dead_while_in_cache_test(void) { @@ -343,6 +358,7 @@ main_f(va_list ap) fiber_join_test(); fiber_stack_test(); fiber_wakeup_self_test(); + fiber_wakeup_dead_test(); fiber_dead_while_in_cache_test(); fiber_flags_respect_test(); cord_cojoin_test(); diff --git a/test/unit/fiber.result b/test/unit/fiber.result index a1bf4381823712efbd64983153bf7df36a6f7371..61f5f05dfb862039b28858889d9487de11ddb40e 100644 --- a/test/unit/fiber.result +++ b/test/unit/fiber.result @@ -19,6 +19,8 @@ OutOfMemory: Failed to allocate 42 bytes in allocator for exception *** fiber_stack_test: done *** *** fiber_wakeup_self_test *** *** fiber_wakeup_self_test: done *** + *** fiber_wakeup_dead_test *** + *** fiber_wakeup_dead_test: done *** *** fiber_dead_while_in_cache_test *** *** fiber_dead_while_in_cache_test: done *** *** fiber_flags_respect_test ***