[Tarantool-patches] [PATCH 01/20] net.box: fix console connection breakage when request is discarded

Vladimir Davydov vdavydov at tarantool.org
Fri Jul 23 14:07:11 MSK 2021


If a timed-out console request is collected by the garbage collector
before the response is processed, the connection will stop serving new
requests. This happens because of the erroneous 'return' statement in
console_sm. Fix it and add a test.
---
 src/box/lua/net_box.c                         |  1 +
 src/box/lua/net_box.lua                       | 20 +++---
 src/lib/core/errinj.h                         |  1 +
 test/box/errinj.result                        |  1 +
 .../net.box_discard_console_request.result    | 62 +++++++++++++++++++
 .../net.box_discard_console_request.test.lua  | 19 ++++++
 test/box/suite.ini                            |  2 +-
 7 files changed, 97 insertions(+), 9 deletions(-)
 create mode 100644 test/box/net.box_discard_console_request.result
 create mode 100644 test/box/net.box_discard_console_request.test.lua

diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index 3f43872ca2e4..ed1df4a189d2 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -542,6 +542,7 @@ check_limit:
 		}
 
 		ev_tstamp deadline = ev_monotonic_now(loop()) + timeout;
+		ERROR_INJECT_YIELD(ERRINJ_NETBOX_IO_DELAY);
 		revents = coio_wait(fd, EV_READ | (ibuf_used(send_buf) != 0 ?
 				EV_WRITE : 0), timeout);
 		luaL_testcancel(L);
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index 3878abf21914..5fd8b96b079d 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -671,6 +671,17 @@ local function create_transport(host, port, user, password, callback,
         request.cond:broadcast()
     end
 
+    local function dispatch_response_console(rid, response)
+        local request = requests[rid]
+        if request == nil then -- nobody is waiting for the response
+            return
+        end
+        request.id = nil
+        requests[rid] = nil
+        request.response = response
+        request.cond:broadcast()
+    end
+
     local function new_request_id()
         local id = next_request_id;
         next_request_id = next_id(id)
@@ -771,14 +782,7 @@ local function create_transport(host, port, user, password, callback,
         if err then
             return error_sm(err, response)
         else
-            local request = requests[rid]
-            if request == nil then -- nobody is waiting for the response
-                return
-            end
-            request.id = nil
-            requests[rid] = nil
-            request.response = response
-            request.cond:broadcast()
+            dispatch_response_console(rid, response)
             return console_sm(next_id(rid))
         end
     end
diff --git a/src/lib/core/errinj.h b/src/lib/core/errinj.h
index e492428071d9..3fe4c7c22cc8 100644
--- a/src/lib/core/errinj.h
+++ b/src/lib/core/errinj.h
@@ -154,6 +154,7 @@ struct errinj {
 	_(ERRINJ_IPROTO_SINGLE_THREAD_STAT, ERRINJ_INT, {.iparam = -1}) \
 	_(ERRINJ_IPROTO_WRITE_ERROR_DELAY, ERRINJ_BOOL, {.bparam = false})\
 	_(ERRINJ_APPLIER_READ_TX_ROW_DELAY, ERRINJ_BOOL, {.bparam = false})\
+	_(ERRINJ_NETBOX_IO_DELAY, ERRINJ_BOOL, {.bparam = false}) \
 
 ENUM0(errinj_id, ERRINJ_LIST);
 extern struct errinj errinjs[];
diff --git a/test/box/errinj.result b/test/box/errinj.result
index 44f86a54e7eb..adb682ac3a5c 100644
--- a/test/box/errinj.result
+++ b/test/box/errinj.result
@@ -63,6 +63,7 @@ evals
   - ERRINJ_IPROTO_WRITE_ERROR_DELAY: false
   - ERRINJ_LOG_ROTATE: false
   - ERRINJ_MEMTX_DELAY_GC: false
+  - ERRINJ_NETBOX_IO_DELAY: false
   - ERRINJ_PORT_DUMP: false
   - ERRINJ_RELAY_BREAK_LSN: -1
   - ERRINJ_RELAY_EXIT_DELAY: 0
diff --git a/test/box/net.box_discard_console_request.result b/test/box/net.box_discard_console_request.result
new file mode 100644
index 000000000000..e8da50a2f648
--- /dev/null
+++ b/test/box/net.box_discard_console_request.result
@@ -0,0 +1,62 @@
+-- test-run result file version 2
+test_run = require('test_run').new()
+ | ---
+ | ...
+fio = require('fio')
+ | ---
+ | ...
+net = require('net.box')
+ | ---
+ | ...
+console = require('console')
+ | ---
+ | ...
+errinj = box.error.injection
+ | ---
+ | ...
+
+console_sock_path = fio.pathjoin(fio.cwd(), 'console.sock')
+ | ---
+ | ...
+_ = fio.unlink(console_sock_path)
+ | ---
+ | ...
+s = console.listen(console_sock_path)
+ | ---
+ | ...
+c = net.connect('unix/', console_sock_path, {console = true})
+ | ---
+ | ...
+
+errinj.set('ERRINJ_NETBOX_IO_DELAY', true)
+ | ---
+ | - ok
+ | ...
+c:eval('return', 0)        -- timeout, but the request is still in flight
+ | ---
+ | - error: Timeout exceeded
+ | ...
+collectgarbage('collect')  -- force garbage collection of the request
+ | ---
+ | - 0
+ | ...
+errinj.set('ERRINJ_NETBOX_IO_DELAY', false)
+ | ---
+ | - ok
+ | ...
+c:eval('return')           -- ok
+ | ---
+ | - '---
+ | 
+ |   ...
+ | 
+ |   '
+ | ...
+
+c:close()
+ | ---
+ | ...
+s:close()
+ | ---
+ | - true
+ | ...
diff --git a/test/box/net.box_discard_console_request.test.lua b/test/box/net.box_discard_console_request.test.lua
new file mode 100644
index 000000000000..52543e1d5649
--- /dev/null
+++ b/test/box/net.box_discard_console_request.test.lua
@@ -0,0 +1,19 @@
+test_run = require('test_run').new()
+fio = require('fio')
+net = require('net.box')
+console = require('console')
+errinj = box.error.injection
+
+console_sock_path = fio.pathjoin(fio.cwd(), 'console.sock')
+_ = fio.unlink(console_sock_path)
+s = console.listen(console_sock_path)
+c = net.connect('unix/', console_sock_path, {console = true})
+
+errinj.set('ERRINJ_NETBOX_IO_DELAY', true)
+c:eval('return', 0)        -- timeout, but the request is still in flight
+collectgarbage('collect')  -- force garbage collection of the request
+errinj.set('ERRINJ_NETBOX_IO_DELAY', false)
+c:eval('return')           -- ok
+
+c:close()
+s:close()
diff --git a/test/box/suite.ini b/test/box/suite.ini
index 5ac3979dbbf4..d9379cc0f28a 100644
--- a/test/box/suite.ini
+++ b/test/box/suite.ini
@@ -5,7 +5,7 @@ script = box.lua
 disabled = rtree_errinj.test.lua tuple_bench.test.lua
 long_run = huge_field_map_long.test.lua
 config = engine.cfg
-release_disabled = errinj.test.lua errinj_index.test.lua rtree_errinj.test.lua upsert_errinj.test.lua iproto_stress.test.lua gh-4648-func-load-unload.test.lua gh-5645-several-iproto-threads.test.lua
+release_disabled = errinj.test.lua errinj_index.test.lua rtree_errinj.test.lua upsert_errinj.test.lua iproto_stress.test.lua gh-4648-func-load-unload.test.lua gh-5645-several-iproto-threads.test.lua box/net.box_discard_console_request.test.lua
 lua_libs = lua/fifo.lua lua/utils.lua lua/bitset.lua lua/index_random_test.lua lua/push.lua lua/identifier.lua lua/txn_proxy.lua
 use_unix_sockets = True
 use_unix_sockets_iproto = True
-- 
2.25.1



More information about the Tarantool-patches mailing list