Tarantool development patches archive
 help / color / mirror / Atom feed
From: Cyrill Gorcunov <gorcunov@gmail.com>
To: tml <tarantool-patches@freelists.org>
Cc: Alexander Turenko <alexander.turenko@tarantool.org>,
	Konstantin Osipov <kostja@tarantool.org>,
	Kirill Yukhin <kyukhin@tarantool.org>,
	Cyrill Gorcunov <gorcunov@gmail.com>
Subject: [tarantool-patches] [PATCH 4/5] box/console: Fix hang in remote console lua mode
Date: Sat, 31 Aug 2019 00:48:07 +0300	[thread overview]
Message-ID: <20190830214808.17422-5-gorcunov@gmail.com> (raw)
In-Reply-To: <20190830214808.17422-1-gorcunov@gmail.com>

If we change output mode on remote machine via
text-based session

 node a (server)
 ------
 require('console').listen('unix/:/tmp/X.sock')
 ...

 node b (client)
 ------
 require('console').connect('unix/:/tmp/X.sock')
 connected to unix/:/tmp/X.sock
 ...
 unix/:/tmp/X.sock> \set output lua

the client get stuck forever, it is because the text
wire protocol waits for yaml eos terminator which of
course never hit the peer, because lua mode uses own
one.

Thus to fix this problem we have to preprocess the text
we're passing to the server, just like we do in local
console. So we reuse command parsing code and remember
current output terminator in text_connection_mt instance.

Another problem is that named default output mode. There
could be a mixed environment where server operates in
default lua mode but client connects with yaml mode. To
break a tie we yield "\set output" command with current
output mode when establishing a connection. Since the
output format is per-session bound this doesn't affect
any other connections on a server.

Part-of #3834
---
 src/box/lua/console.lua | 50 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/src/box/lua/console.lua b/src/box/lua/console.lua
index 006748d93..203dc668c 100644
--- a/src/box/lua/console.lua
+++ b/src/box/lua/console.lua
@@ -158,6 +158,27 @@ local function current_output()
     return d
 end
 
+local function current_eos()
+    local d = current_output()
+    return output_eos[d["fmt"]]
+end
+
+--
+-- Map output format into a "\set" command.
+local function output_cmd_string()
+    local d = current_output()
+    if d["fmt"] == "yaml" then
+        return "\\set output yaml"
+    elseif d["fmt"] == "lua" then
+        local cmd = "\\set output lua"
+        if d["opts"] == "block" then
+            cmd = cmd .. ",block"
+        end
+        return cmd
+    end
+    return ""
+end
+
 local function format(status, ...)
     local d = current_output()
     return output_handlers[d["fmt"]](status, d["opts"], ...)
@@ -341,15 +362,33 @@ local text_connection_mt = {
         -- @retval     nil Error.
         --
         read = function(self)
-            local ret = self._socket:read(YAML_TERM)
+            local ret = self._socket:read(self.eos)
             if ret and ret ~= '' then
                 return ret
             end
         end,
         --
+        -- The command might modify EOS so
+        -- we have to parse and preprocess it
+        -- first to not stuck in :read() forever.
+        preprocess_eval = function(self, text)
+            local command = get_command(text)
+            if command == nil then
+                return
+            end
+            local nr_items, items = parse_operators(command)
+            if nr_items == 3 then
+                local err, fmt, opts = output_parse(items[3])
+                if not err then
+                    self.eos = output_eos[fmt]
+                end
+            end
+        end,
+        --
         -- Write + Read.
         --
         eval = function(self, text)
+            self:preprocess_eval(text)
             text = text..'$EOF$\n'
             if not self:write(text) then
                 error(self:set_error())
@@ -404,9 +443,14 @@ local function wrap_text_socket(connection, url, print_f)
         host = url.host or 'localhost',
         port = url.service,
         print_f = print_f,
+        eos = current_eos(),
     }, text_connection_mt)
-    if not conn:write('require("console").delimiter("$EOF$")\n') or
-       not conn:read() then
+    local cmd_set_output = output_cmd_string() .. '\n'
+    local cmd_delimiter = 'require("console").delimiter("$EOF$")\n'
+    if not conn:write(cmd_set_output) or not conn:read() then
+        conn:set_error()
+    end
+    if not conn:write(cmd_delimiter) or not conn:read() then
         conn:set_error()
     end
     return conn
-- 
2.20.1

  parent reply	other threads:[~2019-08-30 21:49 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-30 21:48 [tarantool-patches] [PATCH v2 0/5] box/console: Improve lua mode for remote console Cyrill Gorcunov
2019-08-30 21:48 ` [tarantool-patches] [PATCH 1/5] box/console: Add mapping for direct symbols Cyrill Gorcunov
     [not found]   ` <20190903082351.GB9438@atlas>
2019-09-03  8:26     ` [tarantool-patches] " Cyrill Gorcunov
     [not found]   ` <20190903082446.GC9438@atlas>
2019-09-03  8:28     ` Cyrill Gorcunov
2019-08-30 21:48 ` [tarantool-patches] [PATCH 2/5] box/console: Add explicit output EOS mapping Cyrill Gorcunov
     [not found]   ` <20190903082725.GD9438@atlas>
2019-09-03  8:32     ` [tarantool-patches] " Cyrill Gorcunov
2019-08-30 21:48 ` [tarantool-patches] [PATCH 3/5] box/console: Refactor command handling Cyrill Gorcunov
2019-08-30 21:48 ` Cyrill Gorcunov [this message]
     [not found]   ` <20190903190002.GC15611@atlas>
2019-09-03 19:18     ` [tarantool-patches] Re: [PATCH 4/5] box/console: Fix hang in remote console lua mode Cyrill Gorcunov
     [not found]       ` <20190904064657.GD30636@atlas>
2019-09-04  7:12         ` Cyrill Gorcunov
2019-08-30 21:48 ` [tarantool-patches] [PATCH 5/5] box/console: Provide console.eos() api Cyrill Gorcunov
     [not found]   ` <20190903190057.GD15611@atlas>
2019-09-03 19:19     ` [tarantool-patches] " Cyrill Gorcunov
     [not found]       ` <20190904064725.GE30636@atlas>
2019-09-04  7:12         ` Cyrill Gorcunov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190830214808.17422-5-gorcunov@gmail.com \
    --to=gorcunov@gmail.com \
    --cc=alexander.turenko@tarantool.org \
    --cc=kostja@tarantool.org \
    --cc=kyukhin@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --subject='Re: [tarantool-patches] [PATCH 4/5] box/console: Fix hang in remote console lua mode' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox