From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id B06EE6EC59; Fri, 29 Jan 2021 16:44:17 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org B06EE6EC59 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1611927857; bh=EkvVaAyhiSAOd1HA9gnYjuoUoaQ0poy3enwwxPaEpZ4=; h=To:References:Date:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=oaRBe5oy1EQiUQclIqaLLlbicsPTYNNGJdZIWTX2p5YMlXkFOcSg5NkWn2JZQxHWr b5BtGJVkhOTgn4JkLcA28wWIcHeR+VWmEIoyOdrn4JpRKq4kXfc14SpsLCSW+wVxsX o4l5NdYIwnuMUUDf3wymAShDS/7/dpNVRneCwTVw= Received: from smtpng2.m.smailru.net (smtpng2.m.smailru.net [94.100.179.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id A61E86EC59 for ; Fri, 29 Jan 2021 16:44:15 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org A61E86EC59 Received: by smtpng2.m.smailru.net with esmtpa (envelope-from ) id 1l5U4M-0007Ky-IH; Fri, 29 Jan 2021 16:44:15 +0300 To: Artem Starshov , Alexander Turenko References: <5c1da95a0d1ed5acdba69d647b6446c4929686b1.1611781593.git.artemreyt@tarantool.org> Message-ID: Date: Fri, 29 Jan 2021 16:44:14 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: <5c1da95a0d1ed5acdba69d647b6446c4929686b1.1611781593.git.artemreyt@tarantool.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD953AC099BC0052A9CD238BCF93DF23716D1711D0DDC4F5AC2182A05F538085040925F71EF1467728EE7BBCB1A0E522DD493DD7B45316ECA87007525988D6B69E2 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE76AB1B6FB25ACEDC9EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006375045C080FAAE96148638F802B75D45FF5571747095F342E8C7A0BC55FA0FE5FC276630D5DB6BA713B27EF44DE737954F3D2FDB93159CC05C389733CBF5DBD5E913377AFFFEAFD269A417C69337E82CC2CC7F00164DA146DAFE8445B8C89999729449624AB7ADAF37F6B57BC7E64490611E7FA7ABCAF51C92A417C69337E82CC2CC7F00164DA146DA6F5DAA56C3B73B23C77107234E2CFBA567F23339F89546C55F5C1EE8F4F765FCA43F4593FF08F5ED75ECD9A6C639B01BBD4B6F7A4D31EC0BC0CAF46E325F83A522CA9DD8327EE493B89ED3C7A62817819EF166FBCB559E95C4224003CC836476C0CAF46E325F83A50BF2EBBBDD9D6B0F05F538519369F3743B503F486389A921A5CC5B56E945C8DA X-B7AD71C0: 6FEFE4C63DFE2D85469AD6E133326EAB664F5199923B286E81C2AD9CFA0FBF5C9C2BBA594F31363B5803BE1F3B17DC36E8F7B195E1C97831E2C3A6F785DAC43F4EBAF99501702FC7 X-C1DE0DAB: 0D63561A33F958A50FC5429BC83F227B51F708DD30F1801FF7544978BF67EA83D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA75F04B387B5D7535DE410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3447DF5779098ECEE9280BCD1067938D37227FC4C8E12348677F5B46A8EFB3DE99F4E0E36B2FEDF4001D7E09C32AA3244CD5D4CDCCC71317AE963E0DBED8DECD633A92A9747B6CC886927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj0axADxPFAF9EL/2ptyhV4w== X-Mailru-Sender: 689FA8AB762F73936BC43F508A063822B929DFA10A62EDFCD22325EB65945654DD788429FD8613638ED9BB8B05EE7B3AFB559BB5D741EB96D19CD4E7312BAA970A04DAD6CC59E33667EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH 2/2] lua: fix tarantool -e always enters interactive mode X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sergey Bronnikov via Tarantool-patches Reply-To: Sergey Bronnikov Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Thanks for the patch! See my 3 comments below. On 28.01.2021 00:15, Artem Starshov wrote: > The reason why tarantool -e always enters interactive mode is that > statement after option -e isn't considered as a script. > > In man PUC-Rio lua there are different names for statement -e (stat) > and script, but they have the same behavior regarding interactive > mode. (Also cases, when interpreter loads stdin, have the same behaviour). > > Fixes #5040 > --- > src/lib/core/errinj.h | 1 + > src/lua/init.c | 20 ++- > ...40-always-enters-interactive-mode.test.lua | 130 ++++++++++++++++++ > test/box/errinj.result | 1 + > 4 files changed, 148 insertions(+), 4 deletions(-) > create mode 100755 test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > > diff --git a/src/lib/core/errinj.h b/src/lib/core/errinj.h > index dc0657614..89d2d3314 100644 > --- a/src/lib/core/errinj.h > +++ b/src/lib/core/errinj.h > @@ -149,6 +149,7 @@ struct errinj { > _(ERRINJ_AUTO_UPGRADE, ERRINJ_BOOL, {.bparam = false})\ > _(ERRINJ_COIO_WRITE_CHUNK, ERRINJ_BOOL, {.bparam = false}) \ > _(ERRINJ_APPLIER_SLOW_ACK, ERRINJ_BOOL, {.bparam = false}) \ > + _(ERRINJ_STDIN_ISATTY, ERRINJ_INT, {.iparam = -1}) \ > > ENUM0(errinj_id, ERRINJ_LIST); > extern struct errinj errinjs[]; > diff --git a/src/lua/init.c b/src/lua/init.c > index 25e8884a6..fc56e7fe0 100644 > --- a/src/lua/init.c > +++ b/src/lua/init.c > @@ -61,6 +61,7 @@ > #include "lua/utf8.h" > #include "lua/swim.h" > #include "lua/decimal.h" > +#include "errinj.h" 1. Looks like it is sorted alphabetically order, so "errinj.h" should be right after "digest.h" header. > #include "digest.h" > #include > > @@ -583,6 +584,7 @@ run_script_f(va_list ap) > */ > struct diag *diag = va_arg(ap, struct diag *); > bool aux_loop_is_run = false; > + bool option_e_runned = false; > > /* > * Load libraries and execute chunks passed by -l and -e > @@ -613,6 +615,7 @@ run_script_f(va_list ap) > if (luaT_call(L, 0, 0) != 0) > goto error; > lua_settop(L, 0); > + option_e_runned = true; > break; > default: > unreachable(); /* checked by getopt() in main() */ > @@ -627,25 +630,34 @@ run_script_f(va_list ap) > fiber_sleep(0.0); > aux_loop_is_run = true; > > + int is_atty; > + struct errinj *inj = errinj(ERRINJ_STDIN_ISATTY, ERRINJ_INT); > + if (inj != NULL && inj->iparam >= 0) { > + is_atty = inj->iparam; > + } else { > + is_atty = isatty(STDIN_FILENO); > + } > + > if (path && strcmp(path, "-") != 0 && access(path, F_OK) == 0) { > /* Execute script. */ > if (luaL_loadfile(L, path) != 0) > goto luajit_error; > if (lua_main(L, argc, argv) != 0) > goto error; > - } else if (!isatty(STDIN_FILENO) || (path && strcmp(path, "-") == 0)) { > + } else if (!is_atty || (path && strcmp(path, "-") == 0)) { > /* Execute stdin */ > if (luaL_loadfile(L, NULL) != 0) > goto luajit_error; > if (lua_main(L, argc, argv) != 0) > goto error; > - } else { > + } else if (!option_e_runned) { > interactive = true; > } > > /* > - * Start interactive mode when it was explicitly requested > - * by "-i" option or stdin is TTY or there are no script. > + * Start interactive mode in any of the cases: > + * - it was explicitly requested by "-i" option; > + * - stdin is TTY and there are no script (-e is considered as a script). > */ > if (interactive) { > say_crit("%s %s\ntype 'help' for interactive help", > diff --git a/test/app-tap/gh-5040-always-enters-interactive-mode.test.lua b/test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > new file mode 100755 > index 000000000..e1a92465e > --- /dev/null > +++ b/test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > @@ -0,0 +1,130 @@ > +#!/usr/bin/env tarantool > + > +local process_timeout = require('process_timeout') > +local ffi = require('ffi') > +local tap = require('tap') > +local fio = require('fio') > + > +-- > +-- Tests to check if the tarantool binary enters > +-- interactive mode or not. > +-- > + > +local build_target = require('tarantool').build.target > +local is_debug = build_target:match('Debug$') ~= nil > + > +local TARANTOOL_PATH = arg[-1] > +local output_file = fio.abspath('out.txt') > +local cmd_end = (' >%s & echo $!'):format(output_file) > + > +-- Like a default timeout for `cond_wait` in test-run > +local process_waiting_timeout = 60.0 > +local file_read_timeout = 60.0 > +local file_read_interval = 0.2 > +local file_open_timeout = 60.0 > + > +-- Each command consists of: > +-- * cmd_args - command line arguments for tarantool binary > +-- * stdin - stdin for tarantool > +-- * interactive - true if interactive mode expected > +-- * empty_output - true if command should have empty output > +local commands = { 2. I would rename table to 'testcases'. > + { > + cmd_args = '', > + stdin = 'tty', > + interactive = true > + }, > + { > + cmd_args = '', > + stdin = '/dev/null', > + interactive = false, > + empty_output = true > + }, > + > + { > + cmd_args = ' -e "print(_VERSION)"', > + stdin = 'tty', > + interactive = false > + }, > + { > + cmd_args = ' -e "print(_VERSION)"', > + stdin = '/dev/null', > + interactive = false > + }, > + > + { > + cmd_args = ' -i -e "print(_VERSION)"', > + stdin = 'tty', > + interactive = true > + }, > + { > + cmd_args = ' -i -e "print(_VERSION)"', > + stdin = '/dev/null', > + interactive = true > + } > +} > + > +local test = tap.test('gh-5040') > + > +if not is_debug then > + test:plan(1) > + test:skip('This test runs only with Debug build. Build: ' .. build_target) > + os.exit(test:check() and 0 or 1) > +end > + > +test:plan(#commands) > +for _, cmd in pairs(commands) do > + local full_cmd = '' > + if cmd.stdin == 'tty' then > + cmd.stdin = '' > + full_cmd = 'ERRINJ_STDIN_ISATTY=1 ' > + else > + cmd.stdin = '< ' .. cmd.stdin > + end > + > + local full_cmd = full_cmd .. ('%s %s %s %s'):format( > + TARANTOOL_PATH, > + cmd.cmd_args, > + cmd.stdin, > + cmd_end > + ) > + test:test(full_cmd, function(test) > + test:plan(cmd.interactive and 1 or 2) > + > + local pid = tonumber(io.popen(full_cmd):read("*line")) > + assert(pid, "pipe error for: " .. cmd.cmd_args) > + > + local fh = process_timeout.open_with_timeout(output_file, > + file_open_timeout) > + assert(fh, 'error while opening ' .. output_file) > + > + if cmd.interactive then > + local data = process_timeout.read_with_timeout(fh, > + file_read_timeout, > + file_read_interval) > + test:like(data, 'tarantool>', 'interactive mode detected') > + else > + local process_completed = process_timeout.wait_process_completion( > + pid, > + process_waiting_timeout) > + test:ok(process_completed, 'process completed') > + > + -- If empty output expected, then don't wait full file_read_timeout > + -- for non-empty output_file, only a little time to be sure that > + -- file is empty. > + local read_timeout = cmd.empty_output and file_read_interval > + or file_read_timeout > + local data = process_timeout.read_with_timeout(fh, read_timeout, > + file_read_interval) > + if cmd.empty_output then > + test:ok(#data == 0, 'output is empty') > + else > + test:unlike(data, 'tarantool>', 'iteractive mode wasn\'t detected') > + end > + end > + if process_timeout.process_is_alive(pid) then ffi.C.kill(pid, 9) end > + fh:close() > + end) > +end > + 3. ~18 tests out of 100 failed when I run with command below:  ../../test/test-run.py --builddir=/home/s.bronnikov/work/tarantool/build --vardir=/home/s.bronnikov/work/tarantool/build/test/var -j 100 $(yes app-tap/gh-5040-always-enters-interactive-mode.test.lua | head -n 100) > +os.exit(test:check() and 0 or 1) > diff --git a/test/box/errinj.result b/test/box/errinj.result > index b8c2476c3..a962dbe2d 100644 > --- a/test/box/errinj.result > +++ b/test/box/errinj.result > @@ -74,6 +74,7 @@ evals > - ERRINJ_SNAP_COMMIT_DELAY: false > - ERRINJ_SNAP_WRITE_DELAY: false > - ERRINJ_SQL_NAME_NORMALIZATION: false > + - ERRINJ_STDIN_ISATTY: -1 > - ERRINJ_SWIM_FD_ONLY: false > - ERRINJ_TESTING: false > - ERRINJ_TUPLE_ALLOC: false