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