[Tarantool-patches] [PATCH v2] core: handle fiber cancellation for fiber.cond
Sergey Ostanevich
sergos at tarantool.org
Thu Nov 12 23:15:23 MSK 2020
Sorry, the patch was not updated. Here’s a new one and the branch is updated
commit 42ea06f7cf69ee6b492cefcbb201bc9bba15c686
Author: Sergey Ostanevich <sergos at tarantool.org>
Date: Tue Nov 3 12:52:26 2020 +0300
core: handle fiber cancellation for fiber.cond
Before this patch fiber.cond():wait() just returns for cancelled
fiber. In contrast fiber.channel():get() threw "fiber is
canceled" error.
This patch unify behaviour of channels and condvars and also fixes
related net.box module problem - it was impossible to interrupt
net.box call with fiber.cancel because it used fiber.cond under
the hood. Test cases for both bugs are added.
Closes #4834
Closes #5013
Co-authored-by: Oleg Babin <olegrok at tarantool.org>
@TarantoolBot document
Title: fiber.cond():wait() throws if fiber is cancelled
Currently fiber.cond():wait() throws an error if waiting fiber is
cancelled.
---
Github: https://gitlab.com/tarantool/tarantool/-/commits/sergos/gh-5013-fiber-cond
Issue: https://github.com/tarantool/tarantool/issues/5013
@Changelog
* fiber.cond().wait() now throws if fiber is cancelled
diff --git a/src/box/box.cc b/src/box/box.cc
index 18568df3b..29f74e94b 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -305,10 +305,9 @@ box_wait_ro(bool ro, double timeout)
{
double deadline = ev_monotonic_now(loop()) + timeout;
while (is_box_configured == false || box_is_ro() != ro) {
- if (fiber_cond_wait_deadline(&ro_cond, deadline) != 0)
- return -1;
- if (fiber_is_cancelled()) {
- diag_set(FiberIsCancelled);
+ if (fiber_cond_wait_deadline(&ro_cond, deadline) != 0) {
+ if (fiber_is_cancelled())
+ diag_set(FiberIsCancelled);
return -1;
}
}
diff --git a/src/lib/core/fiber_cond.c b/src/lib/core/fiber_cond.c
index 904a350d9..cc59eaafb 100644
--- a/src/lib/core/fiber_cond.c
+++ b/src/lib/core/fiber_cond.c
@@ -108,6 +108,11 @@ fiber_cond_wait_timeout(struct fiber_cond *c, double timeout)
diag_set(TimedOut);
return -1;
}
+ if (fiber_is_cancelled()) {
+ if (diag_is_empty(diag_get()))
+ diag_set(FiberIsCancelled);
+ return -1;
+ }
return 0;
}
diff --git a/src/lib/core/fiber_cond.h b/src/lib/core/fiber_cond.h
index 87c6f2ca2..2662e0654 100644
--- a/src/lib/core/fiber_cond.h
+++ b/src/lib/core/fiber_cond.h
@@ -114,7 +114,7 @@ fiber_cond_broadcast(struct fiber_cond *cond);
* @param cond condition
* @param timeout timeout in seconds
* @retval 0 on fiber_cond_signal() call or a spurious wake up
- * @retval -1 on timeout, diag is set to TimedOut
+ * @retval -1 on timeout or fiber cancellation, diag is set
*/
int
fiber_cond_wait_timeout(struct fiber_cond *cond, double timeout);
diff --git a/test/app-tap/gh-5013-fiber-cancel.test.lua b/test/app-tap/gh-5013-fiber-cancel.test.lua
new file mode 100755
index 000000000..ca4ca2c90
--- /dev/null
+++ b/test/app-tap/gh-5013-fiber-cancel.test.lua
@@ -0,0 +1,23 @@
+#!/usr/bin/env tarantool
+
+local tap = require('tap')
+local fiber = require('fiber')
+local test = tap.test("gh-5013-fiber-cancel")
+
+test:plan(2)
+
+local result = {}
+
+function test_f()
+ local cond = fiber.cond()
+ local res, err = pcall(cond.wait, cond)
+ result.res = res
+ result.err = err
+end
+
+local f = fiber.create(test_f)
+f:cancel()
+fiber.yield()
+
+test:ok(result.res == false, 'expected result is false')
+test:ok(tostring(result.err) == 'fiber is cancelled', 'fiber cancellation should be reported')
diff --git a/test/box/net.box_fiber_cancel_gh-4834.result b/test/box/net.box_fiber_cancel_gh-4834.result
new file mode 100644
index 000000000..4ed04bb61
--- /dev/null
+++ b/test/box/net.box_fiber_cancel_gh-4834.result
@@ -0,0 +1,62 @@
+-- test-run result file version 2
+remote = require 'net.box'
+ | ---
+ | ...
+fiber = require 'fiber'
+ | ---
+ | ...
+test_run = require('test_run').new()
+ | ---
+ | ...
+
+-- #4834: Cancelling fiber doesn't interrupt netbox operations
+function infinite_call() fiber.channel(1):get() end
+ | ---
+ | ...
+box.schema.func.create('infinite_call')
+ | ---
+ | ...
+box.schema.user.grant('guest', 'execute', 'function', 'infinite_call')
+ | ---
+ | ...
+
+error_msg = nil
+ | ---
+ | ...
+test_run:cmd("setopt delimiter ';'")
+ | ---
+ | - true
+ | ...
+function netbox_runner()
+ local cn = remote.connect(box.cfg.listen)
+ local f = fiber.new(function()
+ _, error_msg = pcall(cn.call, cn, 'infinite_call')
+ end)
+ f:set_joinable(true)
+ fiber.yield()
+ f:cancel()
+ f:join()
+ cn:close()
+end;
+ | ---
+ | ...
+test_run:cmd("setopt delimiter ''");
+ | ---
+ | - true
+ | ...
+netbox_runner()
+ | ---
+ | ...
+error_msg
+ | ---
+ | - fiber is cancelled
+ | ...
+box.schema.func.drop('infinite_call')
+ | ---
+ | ...
+infinite_call = nil
+ | ---
+ | ...
+error_msg = nil
+ | ---
+ | ...
diff --git a/test/box/net.box_fiber_cancel_gh-4834.test.lua b/test/box/net.box_fiber_cancel_gh-4834.test.lua
new file mode 100644
index 000000000..bc0e5af6e
--- /dev/null
+++ b/test/box/net.box_fiber_cancel_gh-4834.test.lua
@@ -0,0 +1,28 @@
+remote = require 'net.box'
+fiber = require 'fiber'
+test_run = require('test_run').new()
+
+-- #4834: Cancelling fiber doesn't interrupt netbox operations
+function infinite_call() fiber.channel(1):get() end
+box.schema.func.create('infinite_call')
+box.schema.user.grant('guest', 'execute', 'function', 'infinite_call')
+
+error_msg = nil
+test_run:cmd("setopt delimiter ';'")
+function netbox_runner()
+ local cn = remote.connect(box.cfg.listen)
+ local f = fiber.new(function()
+ _, error_msg = pcall(cn.call, cn, 'infinite_call')
+ end)
+ f:set_joinable(true)
+ fiber.yield()
+ f:cancel()
+ f:join()
+ cn:close()
+end;
+test_run:cmd("setopt delimiter ''");
+netbox_runner()
+error_msg
+box.schema.func.drop('infinite_call')
+infinite_call = nil
+error_msg = nil
======================
> On 11 Nov 2020, at 00:16, Sergey Ostanevich <sergos at tarantool.org> wrote:
>
> Hi Leonid, thank you for the review!
>
> I put two parts together to handle them in one patch.
>
>> On 4 Nov 2020, at 13:00, Leonid Vasiliev <lvasiliev at tarantool.org> wrote:
>>
>> Hi! Thank you for the patch.
>> See some comments below:
>>
>> 1) The patch changes undocumented behavior, AFAIU.
>> So, I have a question:"Do you plan to backport the patch to
>> tarantool 1.10?". If the answer is "Yes" - I'm comfortable with the
>> changes. But if the answer is "No" - I will object, because in this case
>> both behaviors must be supported in all modules.
>>
>
> Yes, the plan is to push it down to 1.10
>
>> 2) I think changing the behavior in C doesn't cause much of a problem,
>> because before when you wait without timeout, you don't need to check
>> the return value (it's always 0). But in Lua it will cause the problems,
>> because now throws an error if cancelled and all wait calls should be
>> wrapped to pcall.
>
> Exactly it is the change to Lua and we intentionally make it, since original
> behaviour is wrong. Good things are: fiber.cond has no big presence in the
> /tarantool sourcebase and the cancellation of fiber itself means the fiber
> has to quit.
>
>>
>> On 31.10.2020 19:29, sergos at tarantool.org wrote:
>>> From: Sergey Ostanevich <sergos at tarantool.org>
>>> Hi!
>>> Thanks to Oleg Babin's comment I found there's no need to update any lua
>>> interfaces, since the reason was in C implementation. Also, there is one
>>> place the change is played, so after I fixed it I got complete testing
>>> pass.
>>> Force-pushed branch, v2 patch attached.
>>> Before this patch fiber.cond():wait() just returns for cancelled
>>> fiber. In contrast fiber.channel():get() threw "fiber is
>>> canceled" error.
>>> This patch unify behaviour of channels and condvars and also fixes
>>
>> 3) behaviour -> behavior.
>
> Depends on spellchecker - mine sets it to this British version.
>
>>
>>> related net.box module problem - it was impossible to interrupt
>>> net.box call with fiber.cancel because it used fiber.cond under
>>> the hood. Test cases for both bugs are added.
>>> Closes #4834
>>> Closes #5013
>>> Co-authored-by: Oleg Babin <olegrok at tarantool.org>
>>> @TarantoolBot document
>>> Title: fiber.cond():wait() throws if fiber is cancelled
>>> Currently fiber.cond():wait() throws an error if waiting fiber is
>>> cancelled like in case with fiber.channel():get().
>>
>> 4) I don't think it's a good decision adding a comparison with
>> fiber.channel():get() to the documentation. Up to you.
>>
>
> I’d agree to you: let’s just put the new behaviour here.
>
>> 5) Document the changes in module.h.
>
> Done (need to rebuild, obviously).
>
>>
>>> ---
>>
>> 6) Add @ChangeLog.
>>
>>> Github: https://gitlab.com/tarantool/tarantool/-/commits/sergos/gh-5013-fiber-cond
>>> Issue: https://github.com/tarantool/tarantool/issues/5013
>>> src/box/box.cc | 6 +-
>>> src/lib/core/fiber_cond.c | 1 +
>>> test/app-tap/gh-5013-fiber-cancel.test.lua | 23 +++++++
>>> test/box/net.box_fiber_cancel_gh-4834.result | 65 +++++++++++++++++++
>>> .../box/net.box_fiber_cancel_gh-4834.test.lua | 29 +++++++++
>>> 5 files changed, 120 insertions(+), 4 deletions(-)
>>> create mode 100755 test/app-tap/gh-5013-fiber-cancel.test.lua
>>> create mode 100644 test/box/net.box_fiber_cancel_gh-4834.result
>>> create mode 100644 test/box/net.box_fiber_cancel_gh-4834.test.lua
>>
>>> diff --git a/src/box/box.cc b/src/box/box.cc
>>> index 18568df3b..9e824453d 100644
>>> --- a/src/box/box.cc
>>> +++ b/src/box/box.cc
>>> @@ -305,10 +305,8 @@ box_wait_ro(bool ro, double timeout)
>>> {
>>> double deadline = ev_monotonic_now(loop()) + timeout;
>>> while (is_box_configured == false || box_is_ro() != ro) {
>>> - if (fiber_cond_wait_deadline(&ro_cond, deadline) != 0)
>>> - return -1;
>>> - if (fiber_is_cancelled()) {
>>> - diag_set(FiberIsCancelled);
>>> + if (fiber_cond_wait_deadline(&ro_cond, deadline) != 0) {
>>> + if (fiber_is_cancelled()) diag_set(FiberIsCancelled);
>>
>> 7) According to https://www.tarantool.io/en/doc/latest/dev_guide/c_style_guide/
>> it's seems like you are trying to hide something)
>> Use:
>> ```
>> if (condition)
>> action();
>> ```
>> Instead of:
>> ```
>> if (condition) action();
>> another_action();
>> ```
>
> Fixed.
>
>>> return -1;
>>> }
>>> }
>>> diff --git a/src/lib/core/fiber_cond.c b/src/lib/core/fiber_cond.c
>>> index 904a350d9..0c93c5842 100644
>>> --- a/src/lib/core/fiber_cond.c
>>> +++ b/src/lib/core/fiber_cond.c
>>> @@ -108,6 +108,10 @@ fiber_cond_wait_timeout(struct fiber_cond *c, double timeout)
>>> diag_set(TimedOut);
>>> return -1;
>>> }
>>> + if (fiber_is_cancelled()) {
>>> + if (diag_is_empty(diag_get())) diag_set(FiberIsCancelled);
>>
>> 8) The same as previously:
>> ```
>> if (condition)
>> action();
>> ```
>>
>
> Fixed.
>
>> 9) Checking diag on empty looks strange to me. I think we should add an
>> error to diag without this check. If we want to save the previous error,
>> I suggest to use the stack diag.
>
> I made this because this interface is used inside the testing machinery, where
> exact cause of e.g. replica disconnection is reported. If we put the diag here
> unconditionally it will break this use of diag. I believe the stack diag also
> is not supported there yet.
>
>
>>> + return -1;
>>> + }
>>> return 0;
>>> }
>>> diff --git a/test/app-tap/gh-5013-fiber-cancel.test.lua b/test/app-tap/gh-5013-fiber-cancel.test.lua
>>> new file mode 100755
>>> index 000000000..ae805c5bf
>>> --- /dev/null
>>> +++ b/test/app-tap/gh-5013-fiber-cancel.test.lua
>>> @@ -0,0 +1,23 @@
>>> +#!/usr/bin/env tarantool
>>> +
>>> +local tap = require('tap')
>>> +local fiber = require('fiber')
>>> +local test = tap.test("gh-5013-fiber-cancel")
>>> +
>>> +test:plan(2)
>>> +
>>> +local result = {}
>>> +
>>> +function test_f()
>>> + local cond = fiber.cond()
>>> + local res, err = pcall(cond.wait, cond)
>>> + result.res = res
>>> + result.err = err
>>> +end
>>> +
>>> +local f = fiber.create(test_f)
>>> +f:cancel()
>>> +fiber.yield()
>>> +
>>> +test:ok(result.res == false, tostring(result.res))
>>> +test:ok(tostring(result.err) == 'fiber is cancelled', tostring(result.err))
>>
>> 10) Use a user-frendly check message (in both checks).
>>
> Fixed
>
>>> diff --git a/test/box/net.box_fiber_cancel_gh-4834.result b/test/box/net.box_fiber_cancel_gh-4834.result
>>> new file mode 100644
>>> index 000000000..eab0a5e4d
>>> --- /dev/null
>>> +++ b/test/box/net.box_fiber_cancel_gh-4834.result
>>> @@ -0,0 +1,65 @@
>>> +-- test-run result file version 2
>>> +remote = require 'net.box'
>>> + | ---
>>> + | ...
>>> +fiber = require 'fiber'
>>> + | ---
>>> + | ...
>>> +test_run = require('test_run').new()
>>> + | ---
>>> + | ...
>>> +
>>> +-- #4834: Cancelling fiber doesn't interrupt netbox operations
>>> +function infinite_call() fiber.channel(1):get() end
>>> + | ---
>>> + | ...
>>> +box.schema.func.create('infinite_call')
>>> + | ---
>>> + | ...
>>> +box.schema.user.grant('guest', 'execute', 'function', 'infinite_call')
>>> + | ---
>>> + | ...
>>> +
>>> +error_msg = nil
>>> + | ---
>>> + | ...
>>> +test_run:cmd("setopt delimiter ';'")
>>> + | ---
>>> + | - true
>>> + | ...
>>> +function gh4834( > + local cn = remote.connect(box.cfg.listen)
>>> + local f = fiber.new(function()
>>> + _, error_msg = pcall(cn.call, cn, 'infinite_call')
>>> + end)
>>> + f:set_joinable(true)
>>> + fiber.yield()
>>> + f:cancel()
>>> + f:join()
>>> + cn:close()
>>> +end;
>>> + | ---
>>> + | ...
>>> +test_run:cmd("setopt delimiter ''");
>>> + | ---
>>> + | - true
>>> + | ...
>>> +gh4834()
>>> + | ---
>>> + | ...
>>> +error_msg
>>> + | ---
>>> + | - fiber is cancelled
>>> + | ...
>>> +box.schema.func.drop('infinite_call')
>>> + | ---
>>> + | ...
>>> +infinite_call = nil
>>> + | ---
>>> + | ...
>>> +channel = nil
>>> + | ---
>>> + | ...
>>> +error_msg = nil
>>> + | ---
>>> + | ...
>>> diff --git a/test/box/net.box_fiber_cancel_gh-4834.test.lua b/test/box/net.box_fiber_cancel_gh-4834.test.lua
>>> new file mode 100644
>>> index 000000000..06fb3ceac
>>> --- /dev/null
>>> +++ b/test/box/net.box_fiber_cancel_gh-4834.test.lua
>>> @@ -0,0 +1,29 @@
>>> +remote = require 'net.box'
>>> +fiber = require 'fiber'
>>> +test_run = require('test_run').new()
>>> +
>>> +-- #4834: Cancelling fiber doesn't interrupt netbox operations
>>> +function infinite_call() fiber.channel(1):get() end
>>> +box.schema.func.create('infinite_call')
>>> +box.schema.user.grant('guest', 'execute', 'function', 'infinite_call')
>>> +
>>> +error_msg = nil
>>> +test_run:cmd("setopt delimiter ';'")
>>> +function gh4834()
>>
>> 11) I think this is not a self-documenting name for the function.
>>
> Renamed.
>
>>> + local cn = remote.connect(box.cfg.listen)
>>> + local f = fiber.new(function()
>>> + _, error_msg = pcall(cn.call, cn, 'infinite_call')
>>> + end)
>>> + f:set_joinable(true)
>>> + fiber.yield()
>>> + f:cancel()
>>> + f:join()
>>> + cn:close()
>>> +end;
>>> +test_run:cmd("setopt delimiter ''");
>>> +gh4834()
>>> +error_msg
>>> +box.schema.func.drop('infinite_call')
>>> +infinite_call = nil
>>> +channel = nil
>>
>> 12) You didn't introduce the variable "channel". In addition, I looked
>> at a couple of tests and didn't see them cleaning up variables. But I
>> don't mind.
>>
> Removed this one. In general, clean up prevents flaky.
>
>>> +error_msg = nil
>
> =================
>
> Before this patch fiber.cond():wait() just returns for cancelled
> fiber. In contrast fiber.channel():get() threw "fiber is
> canceled" error.
> This patch unify behaviour of channels and condvars and also fixes
> related net.box module problem - it was impossible to interrupt
> net.box call with fiber.cancel because it used fiber.cond under
> the hood. Test cases for both bugs are added.
>
> Closes #4834
> Closes #5013
>
> Co-authored-by: Oleg Babin <olegrok at tarantool.org>
>
> @TarantoolBot document
> Title: fiber.cond():wait() throws if fiber is cancelled
>
> Currently fiber.cond():wait() throws an error if waiting fiber is
> cancelled.
> ---
>
> Github: https://gitlab.com/tarantool/tarantool/-/commits/sergos/gh-5013-fiber-cond
> Issue: https://github.com/tarantool/tarantool/issues/5013
>
> @Changelog
> * fiber.cond().wait() now throws if fiber is cancelled
>
> src/box/box.cc | 6 +-
> src/lib/core/fiber_cond.c | 4 ++
> test/app-tap/gh-5013-fiber-cancel.test.lua | 23 +++++++
> test/box/net.box_fiber_cancel_gh-4834.result | 65 +++++++++++++++++++
> .../box/net.box_fiber_cancel_gh-4834.test.lua | 29 +++++++++
> 5 files changed, 123 insertions(+), 4 deletions(-)
> create mode 100755 test/app-tap/gh-5013-fiber-cancel.test.lua
> create mode 100644 test/box/net.box_fiber_cancel_gh-4834.result
> create mode 100644 test/box/net.box_fiber_cancel_gh-4834.test.lua
>
> diff --git a/src/box/box.cc b/src/box/box.cc
> index 18568df3b..9e824453d 100644
> --- a/src/box/box.cc
> +++ b/src/box/box.cc
> @@ -305,10 +305,8 @@ box_wait_ro(bool ro, double timeout)
> {
> double deadline = ev_monotonic_now(loop()) + timeout;
> while (is_box_configured == false || box_is_ro() != ro) {
> - if (fiber_cond_wait_deadline(&ro_cond, deadline) != 0)
> - return -1;
> - if (fiber_is_cancelled()) {
> - diag_set(FiberIsCancelled);
> + if (fiber_cond_wait_deadline(&ro_cond, deadline) != 0) {
> + if (fiber_is_cancelled()) diag_set(FiberIsCancelled);
> return -1;
> }
> }
> diff --git a/src/lib/core/fiber_cond.c b/src/lib/core/fiber_cond.c
> index 904a350d9..0c93c5842 100644
> --- a/src/lib/core/fiber_cond.c
> +++ b/src/lib/core/fiber_cond.c
> @@ -108,6 +108,10 @@ fiber_cond_wait_timeout(struct fiber_cond *c, double timeout)
> diag_set(TimedOut);
> return -1;
> }
> + if (fiber_is_cancelled()) {
> + if (diag_is_empty(diag_get())) diag_set(FiberIsCancelled);
> + return -1;
> + }
> return 0;
> }
>
> diff --git a/test/app-tap/gh-5013-fiber-cancel.test.lua b/test/app-tap/gh-5013-fiber-cancel.test.lua
> new file mode 100755
> index 000000000..34711fb31
> --- /dev/null
> +++ b/test/app-tap/gh-5013-fiber-cancel.test.lua
> @@ -0,0 +1,23 @@
> +#!/usr/bin/env tarantool
> +
> +local tap = require('tap')
> +local fiber = require('fiber')
> +local test = tap.test("gh-5013-fiber-cancel")
> +
> +test:plan(2)
> +
> +local result = {}
> +
> +function test_f()
> + local cond = fiber.cond()
> + local res, err = pcall(cond.wait, cond)
> + result.res = res
> + result.err = err
> +end
> +
> +local f = fiber.create(test_f)
> +f:cancel()
> +fiber.yield()
> +
> +test:ok(result.res == false, tostring(result.res))
> +test:ok(tostring(result.err) == 'fiber is cancelled', tostring(result.err))
> diff --git a/test/box/net.box_fiber_cancel_gh-4834.result b/test/box/net.box_fiber_cancel_gh-4834.result
> new file mode 100644
> index 000000000..eab0a5e4d
> --- /dev/null
> +++ b/test/box/net.box_fiber_cancel_gh-4834.result
> @@ -0,0 +1,65 @@
> +-- test-run result file version 2
> +remote = require 'net.box'
> + | ---
> + | ...
> +fiber = require 'fiber'
> + | ---
> + | ...
> +test_run = require('test_run').new()
> + | ---
> + | ...
> +
> +-- #4834: Cancelling fiber doesn't interrupt netbox operations
> +function infinite_call() fiber.channel(1):get() end
> + | ---
> + | ...
> +box.schema.func.create('infinite_call')
> + | ---
> + | ...
> +box.schema.user.grant('guest', 'execute', 'function', 'infinite_call')
> + | ---
> + | ...
> +
> +error_msg = nil
> + | ---
> + | ...
> +test_run:cmd("setopt delimiter ';'")
> + | ---
> + | - true
> + | ...
> +function gh4834()
> + local cn = remote.connect(box.cfg.listen)
> + local f = fiber.new(function()
> + _, error_msg = pcall(cn.call, cn, 'infinite_call')
> + end)
> + f:set_joinable(true)
> + fiber.yield()
> + f:cancel()
> + f:join()
> + cn:close()
> +end;
> + | ---
> + | ...
> +test_run:cmd("setopt delimiter ''");
> + | ---
> + | - true
> + | ...
> +gh4834()
> + | ---
> + | ...
> +error_msg
> + | ---
> + | - fiber is cancelled
> + | ...
> +box.schema.func.drop('infinite_call')
> + | ---
> + | ...
> +infinite_call = nil
> + | ---
> + | ...
> +channel = nil
> + | ---
> + | ...
> +error_msg = nil
> + | ---
> + | ...
> diff --git a/test/box/net.box_fiber_cancel_gh-4834.test.lua b/test/box/net.box_fiber_cancel_gh-4834.test.lua
> new file mode 100644
> index 000000000..06fb3ceac
> --- /dev/null
> +++ b/test/box/net.box_fiber_cancel_gh-4834.test.lua
> @@ -0,0 +1,29 @@
> +remote = require 'net.box'
> +fiber = require 'fiber'
> +test_run = require('test_run').new()
> +
> +-- #4834: Cancelling fiber doesn't interrupt netbox operations
> +function infinite_call() fiber.channel(1):get() end
> +box.schema.func.create('infinite_call')
> +box.schema.user.grant('guest', 'execute', 'function', 'infinite_call')
> +
> +error_msg = nil
> +test_run:cmd("setopt delimiter ';'")
> +function gh4834()
> + local cn = remote.connect(box.cfg.listen)
> + local f = fiber.new(function()
> + _, error_msg = pcall(cn.call, cn, 'infinite_call')
> + end)
> + f:set_joinable(true)
> + fiber.yield()
> + f:cancel()
> + f:join()
> + cn:close()
> +end;
> +test_run:cmd("setopt delimiter ''");
> +gh4834()
> +error_msg
> +box.schema.func.drop('infinite_call')
> +infinite_call = nil
> +channel = nil
> +error_msg = nil
> --
> 2.29.2
More information about the Tarantool-patches
mailing list