<div dir="ltr">Receive function behaved inconsistently for the cases where<br>first we use an integer as a pattern as to tell the function<br>a specific number of elements we want to read, and then<br>perform another receive call using '*a' as a pattern.<br>The latter should have denoted that we want to get all there<br>is to get, but instead it was possible to get only a part of<br>data and also in non-sequential order.<br><br>Closes #4118<br>---<br>Branch:<br><a href="https://github.com/tarantool/tarantool/tree/eljashm/gh-4118-socket_tcp_now_consistent">https://github.com/tarantool/tarantool/tree/eljashm/gh-4118-socket_tcp_now_consistent</a><br><br>Issue: <br><a href="https://github.com/tarantool/tarantool/issues/4118">https://github.com/tarantool/tarantool/issues/4118</a> <br><br> src/lua/socket.lua       | 15 ++++++++++++-<br> test/app/socket.result   | 48 ++++++++++++++++++++++++++++++++++++++++<br> test/app/socket.test.lua | 16 ++++++++++++++<br> 3 files changed, 78 insertions(+), 1 deletion(-)<br><br>diff --git a/src/lua/socket.lua b/src/lua/socket.lua<br>index 2dba0a8d2..a334ad45b 100644<br>--- a/src/lua/socket.lua<br>+++ b/src/lua/socket.lua<br>@@ -637,6 +637,19 @@ local function check_limit(self, limit)<br>     return nil<br> end<br> <br>+local function check_infinity(self, limit)<br>+    if limit == 0 then<br>+        return 0<br>+    end<br>+<br>+    local rbuf = self.rbuf<br>+    if rbuf:size() == 0 then<br>+        return nil<br>+    end<br>+<br>+    return rbuf:size()<br>+end<br>+<br> local function check_delimiter(self, limit, eols)<br>     if limit == 0 then<br>         return 0<br>@@ -1454,7 +1467,7 @@ local function lsocket_tcp_receive(self, pattern, prefix)<br>         local result = { prefix }<br>         local deadline = fiber.clock() + (self.timeout or TIMEOUT_INFINITY)<br>         repeat<br>-            local data = socket_sysread(self)<br>+            local data = read(self, LIMIT_INFINITY, timeout, check_infinity)<br>             if data == nil then<br>                 if not errno_is_transient[self._errno] then<br>                     return nil, socket_error(self)<br>diff --git a/test/app/socket.result b/test/app/socket.result<br>index 0d029039a..77eff7370 100644<br>--- a/test/app/socket.result<br>+++ b/test/app/socket.result<br>@@ -2874,3 +2874,51 @@ test_run:cmd("clear filter")<br> ---<br> - true<br> ...<br>+-- case: sicket receive inconsistent behavior<br>+chan = fiber.channel()<br>+---<br>+...<br>+counter = 0<br>+---<br>+...<br>+fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end<br>+---<br>+...<br>+srv = socket.tcp_server('0.0.0.0', 8888, fn)<br>+---<br>+...<br>+s = socket.connect('localhost', 8888)<br>+---<br>+...<br>+chan:put(5)<br>+---<br>+- true<br>+...<br>+chan:put(5)<br>+---<br>+- true<br>+...<br>+s:receive(5)<br>+---<br>+- '00000'<br>+...<br>+chan:put(5)<br>+---<br>+- true<br>+...<br>+s:settimeout(1)<br>+---<br>+- 1<br>+...<br>+s:receive('*a')<br>+---<br>+- '1111122222'<br>+...<br>+s:close()<br>+---<br>+- 1<br>+...<br>+srv:close()<br>+---<br>+- true<br>+...<br>diff --git a/test/app/socket.test.lua b/test/app/socket.test.lua<br>index dab168f90..7ae9a98aa 100644<br>--- a/test/app/socket.test.lua<br>+++ b/test/app/socket.test.lua<br>@@ -983,3 +983,19 @@ client:read(1, 5) == ''<br> server:close()<br> <br> test_run:cmd("clear filter")<br>+<br>+-- case: sicket receive inconsistent behavior<br>+chan = fiber.channel()<br>+counter = 0<br>+fn = function(s) counter = 0; while true do s:write((tostring(counter)):rep(chan:get())); counter = counter + 1 end end<br>+srv = socket.tcp_server('0.0.0.0', 8888, fn)<br>+s = socket.connect('localhost', 8888)<br>+chan:put(5)<br>+chan:put(5)<br>+s:receive(5)<br>+chan:put(5)<br>+s:settimeout(1)<br>+s:receive('*a')<br>+s:close()<br>+srv:close()<br>+<br>-- <br>2.20.1<br></div>