Skip to content
Snippets Groups Projects
Commit 4bf52367 authored by Ilya Verbin's avatar Ilya Verbin Committed by Aleksandr Lyapunov
Browse files

wal: allow spurious wakeups in wal_write

It's possible to wakeup a fiber, which is waiting for WAL write
completion, using Tarantool C API. This results in an error like:
```
main/118/lua F> Journal result code -1 can't be converted to an error
```

This patch introduces a flag, which is set when WAL write is
finished, that allows fibers to yield until the flag is set.

Closes #6506

NO_DOC=bugfix
parent 0dc60b5f
No related branches found
No related tags found
No related merge requests found
## bugfix/core
* Allowed spurious wakeup of a fiber, which is waiting for WAL write completion
(gh-6506).
......@@ -101,6 +101,11 @@ struct journal_entry {
* Approximate size of this request when encoded.
*/
size_t approx_len;
/**
* Set to true when execution of a batch that contains this
* journal entry is completed.
*/
bool is_complete;
/**
* The number of rows in the request.
*/
......@@ -128,6 +133,7 @@ journal_entry_create(struct journal_entry *entry, size_t n_rows,
entry->n_rows = n_rows;
entry->res = JOURNAL_ENTRY_ERR_UNKNOWN;
entry->flags = 0;
entry->is_complete = false;
}
/**
......@@ -244,6 +250,8 @@ journal_async_complete(struct journal_entry *entry)
{
assert(entry->write_async_cb != NULL);
entry->is_complete = true;
journal_queue_on_complete(entry);
entry->write_async_cb(entry);
......
......@@ -1309,9 +1309,10 @@ wal_write(struct journal *journal, struct journal_entry *entry)
if (wal_write_async(journal, entry) != 0)
return -1;
bool cancellable = fiber_set_cancellable(false);
fiber_yield();
fiber_set_cancellable(cancellable);
assert(!entry->is_complete);
do {
fiber_yield();
} while (!entry->is_complete);
return 0;
}
......
......@@ -60,6 +60,7 @@ add_subdirectory(app)
add_subdirectory(app-tap)
add_subdirectory(box)
add_subdirectory(box-tap)
add_subdirectory(box-luatest)
add_subdirectory(sql-tap)
add_subdirectory(sql-luatest)
if(ENABLE_FUZZER)
......
build_module(gh_6506_lib gh_6506_wakeup_writing_to_wal_fiber.c)
#include "module.h"
static struct fiber *saved = NULL;
int
save_fiber(box_function_ctx_t *ctx, const char *args, const char *args_end)
{
saved = fiber_self();
return 0;
}
int
wakeup_saved(box_function_ctx_t *ctx, const char *args, const char *args_end)
{
fiber_wakeup(saved);
return 0;
}
local server = require('test.luatest_helpers.server')
local t = require('luatest')
local g = t.group()
g.before_all = function()
g.server = server:new{alias = 'master'}
g.server:start()
end
g.after_all = function()
g.server:drop()
end
g.test_wakeup_writing_to_wal_fiber = function()
g.server:exec(function()
local t = require('luatest')
local fiber = require('fiber')
local build_path = os.getenv("BUILDDIR")
package.cpath = build_path..'/test/box-luatest/?.so;'..build_path..'/test/box-luatest/?.dylib;'..package.cpath
local lib = box.lib.load('gh_6506_lib')
local save_fiber = lib:load('save_fiber')
local wakeup_saved = lib:load('wakeup_saved')
local s = box.schema.create_space('test')
s:create_index('pk')
local f = fiber.new(function()
save_fiber()
s:replace{1}
fiber.yield()
end)
f:set_joinable(true)
-- Start fiber f
fiber.yield()
-- Wakeup f while it is writing to WAL
wakeup_saved()
-- Check that f did not crash
local st, _ = f:join()
t.assert(st)
end)
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment