From: Serge Petrenko via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>, tarantool-patches@dev.tarantool.org, gorcunov@gmail.com Subject: Re: [Tarantool-patches] [PATCH 1/2] fiber: make wakeup in Lua and C nop on self Date: Sun, 25 Apr 2021 12:21:35 +0300 [thread overview] Message-ID: <2e89c2b4-fd13-2ca1-9c05-f8e95d2e92e6@tarantool.org> (raw) In-Reply-To: <8c48e98e0c9780e2fe4ffbf511ac95678561fcfe.1619219639.git.v.shpilevoy@tarantool.org> 24.04.2021 02:15, Vladislav Shpilevoy пишет: > fiber.wakeup() in Lua and fiber_wakeup() in C could lead to a > crash or undefined behaviour when called on the currently running > fiber. > > In particular, if after wakeup was started a new fiber in a > blocking way (fiber.create() and fiber_start()) it would crash in > debug build, and lead to unknown results in release. > > If after wakeup was made a sleep with non-zero timeout or an > infinite yield (fiber_yield()), the fiber woke up in the same > event loop iteration regardless of any timeout or other wakeups. > It was a spurious wakeup, which is not expected in most of the > places internally. > > The patch makes the wakeup nop on the current fiber making it safe > to use anywhere. > > Closes #5292 > Closes #6043 > > @TarantoolBot document > Title: fiber.wakeup() in Lua and fiber_wakeup() in C are nop on self > In Lua `fiber.wakeup()` being called on the current fiber does not > do anything, safe to use. The same for `fiber_wakeup()` in C. > --- Thanks for the patch! LGTM, generally, with one test-related comment. ... > diff --git a/test/app-tap/gh-6043-fiber-wakeup-self.test.lua b/test/app-tap/gh-6043-fiber-wakeup-self.test.lua > new file mode 100755 > index 000000000..082c1228d > --- /dev/null > +++ b/test/app-tap/gh-6043-fiber-wakeup-self.test.lua > @@ -0,0 +1,50 @@ > +#!/usr/bin/env tarantool > + > +local tap = require('tap') > +local fiber = require('fiber') > + > +-- > +-- gh-6043: fiber.wakeup() on self could lead to a crash if followed by > +-- fiber.create(). Also it could lead to spurious wakeup if followed by a sleep > +-- with non-zero timeout, or by, for example, an infinite yield such as WAL > +-- write. > +-- > + > +local function test_wakeup_self_and_call(test) > + test:plan(3) > + > + local self = fiber.self() > + fiber.wakeup(self) > + local count = 0 > + local f = fiber.create(function() > + count = count + 1 > + fiber.yield() > + count = count + 1 > + end) > + test:is(count, 1, 'created a fiber') > + fiber.yield() > + test:is(count, 2, 'it yielded') > + test:is(f:status(), 'dead', 'and ended') > +end > + > +local function test_wakeup_self_and_wal_write(test) > + test:plan(1) > + > + local s = box.schema.create_space('test') > + s:create_index('pk') > + > + fiber.wakeup(fiber.self()) > + local lsn = box.info.lsn > + s:replace{1} > + test:is(box.info.lsn, lsn + 1, 'written to WAL') > + s:drop() > +end Again, shouldn't everything related to space creation, WAL writes and so on reside in box-tap ? I may be wrong, just asking. > + > +box.cfg{} > + > +local test = tap.test('gh-6043-fiber-wakeup-self') > +test:plan(2) > +test:test('wakeup self + call', test_wakeup_self_and_call) > +test:test('wakeup self + wal write', test_wakeup_self_and_wal_write) > + > +os.exit(test:check() and 0 or 1) > diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc > index 9c1a23bdd..a1e3ded87 100644 > --- a/test/unit/fiber.cc > +++ b/test/unit/fiber.cc > @@ -138,8 +138,7 @@ fiber_join_test() > fiber_set_joinable(fiber, true); > fiber_wakeup(fiber); > /** Let the fiber schedule */ > - fiber_wakeup(fiber()); > - fiber_yield(); > + fiber_reschedule(); > note("by this time the fiber should be dead already"); > fiber_cancel(fiber); > fiber_join(fiber); > @@ -201,12 +200,42 @@ fiber_name_test() > footer(); > } > > +static void > +fiber_wakeup_self_test() > +{ > + header(); > + > + struct fiber *f = fiber(); > + > + fiber_wakeup(f); > + double duration = 0.001; > + uint64_t t1 = fiber_clock64(); > + fiber_sleep(duration); > + uint64_t t2 = fiber_clock64(); > + /* > + * It was a real sleep, not 0 duration. Wakeup is nop on the running > + * fiber. > + */ > + assert(t2 - t1 >= duration); > + > + /* > + * Wakeup + start of a new fiber. This is different from yield but > + * works without crashes too. > + */ > + struct fiber *newf = fiber_new_xc("nop", noop_f); > + fiber_wakeup(f); > + fiber_start(newf); > + > + footer(); > +} > + > static int > main_f(va_list ap) > { > fiber_name_test(); > fiber_join_test(); > fiber_stack_test(); > + fiber_wakeup_self_test(); > ev_break(loop(), EVBREAK_ALL); > return 0; > } > diff --git a/test/unit/fiber.result b/test/unit/fiber.result > index a61e0a2b8..36bf2a599 100644 > --- a/test/unit/fiber.result > +++ b/test/unit/fiber.result > @@ -17,3 +17,5 @@ SystemError Failed to allocate 42 bytes in allocator for exception: Cannot alloc > # normal-stack fiber not crashed > # big-stack fiber not crashed > *** fiber_stack_test: done *** > + *** fiber_wakeup_self_test *** > + *** fiber_wakeup_self_test: done *** > diff --git a/test/unit/fiber_stress.cc b/test/unit/fiber_stress.cc > index 44ab12487..aa892d0a0 100644 > --- a/test/unit/fiber_stress.cc > +++ b/test/unit/fiber_stress.cc > @@ -9,10 +9,8 @@ enum { > static int > yield_f(va_list ap) > { > - for (int i = 0; i < ITERATIONS; i++) { > - fiber_wakeup(fiber()); > - fiber_yield(); > - } > + for (int i = 0; i < ITERATIONS; i++) > + fiber_reschedule(); > return 0; > } > -- Serge Petrenko
next prev parent reply other threads:[~2021-04-25 9:21 UTC|newest] Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-04-23 23:15 [Tarantool-patches] [PATCH 0/2] fiber_wakeup() " Vladislav Shpilevoy via Tarantool-patches 2021-04-23 23:15 ` [Tarantool-patches] [PATCH 1/2] fiber: make wakeup in Lua and C " Vladislav Shpilevoy via Tarantool-patches 2021-04-25 9:21 ` Serge Petrenko via Tarantool-patches [this message] 2021-04-25 15:53 ` Vladislav Shpilevoy via Tarantool-patches 2021-04-26 9:21 ` Serge Petrenko via Tarantool-patches 2021-04-23 23:15 ` [Tarantool-patches] [PATCH 2/2] fiber: use wakeup safely on self everywhere Vladislav Shpilevoy via Tarantool-patches 2021-04-25 9:23 ` Serge Petrenko via Tarantool-patches 2021-04-26 21:56 ` [Tarantool-patches] [PATCH 0/2] fiber_wakeup() nop on self Cyrill Gorcunov via Tarantool-patches 2021-04-27 12:03 ` 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=2e89c2b4-fd13-2ca1-9c05-f8e95d2e92e6@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 1/2] fiber: make wakeup in Lua and C nop on self' \ /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