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 022206EC58; Sat, 20 Feb 2021 13:05:44 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 022206EC58 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1613815544; bh=d4+xpQcKnhVHrCRwBrDIfCEnXi9PeL/RWU6hkcV4AsU=; 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=kJrHHweENAQ3bpKIcRKO+ojbGWObC+zu7H/447QNCaIJnqlf/l/VqQ79A0XcmSvEj mJNUS4uWk+Td/xYSuZDUY9u518gF3lVub6S9sS+UghzDzJxUWYdPrD8vhyNto2u810 kMn+fjlPIEFcJ8Kfic0ioAXToqEoPcVFgP+46Ho8= Received: from smtpng1.m.smailru.net (smtpng1.m.smailru.net [94.100.181.251]) (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 63DB86EC58 for ; Sat, 20 Feb 2021 13:05:42 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 63DB86EC58 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1lDP8v-0002TO-6c; Sat, 20 Feb 2021 13:05:41 +0300 To: Artem Starshov , Alexander Turenko References: <612d38a3f3349c1c8cb6d3f549fd85720b7a1a23.1613674486.git.artemreyt@tarantool.org> Message-ID: Date: Sat, 20 Feb 2021 13:05:40 +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: <612d38a3f3349c1c8cb6d3f549fd85720b7a1a23.1613674486.git.artemreyt@tarantool.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: en-US X-7564579A: 78E4E2B564C1792B X-77F55803: 4F1203BC0FB41BD975C3EC174F56692242B8E6687D03D8974314021AB65B8FCC182A05F538085040FA4CA4B2B237B8D2298C68633380915D8EE054DA018FC169EA19E05F944638DB X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE761966F250AC1AE21EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F7900637FC0948D7756001208638F802B75D45FF5571747095F342E8C7A0BC55FA0FE5FCBE462577C01A1BBA16262854C6EE31E97A2919702A4D20CF389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C07E7E81EEA8A9722B8941B15DA834481FCF19DD082D7633A0EF3E4896CB9E6436389733CBF5DBD5E9D5E8D9A59859A8B64854413538E1713FCC7F00164DA146DA6F5DAA56C3B73B23C77107234E2CFBA567F23339F89546C55F5C1EE8F4F765FC80B9CEB5436E71E375ECD9A6C639B01BBD4B6F7A4D31EC0BC0CAF46E325F83A522CA9DD8327EE4930A3850AC1BE2E7355E97997F8902A7B9C4224003CC836476C0CAF46E325F83A50BF2EBBBDD9D6B0F5D41B9178041F3E72623479134186CDE6BA297DBC24807EABDAD6C7F3747799A X-C1DE0DAB: 0D63561A33F958A5C22070BC55760D7ABC4527A2084EC635F05C41F9B09504BED59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA75448CF9D3A7B2C848410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D348B532EA2091F4FF6540ED94A733CCB30D7D600FE47814047E1EF79FCABDB0C7D63196B2934E82A581D7E09C32AA3244C9FD0FF9B28DE14147B7B957272930FC5A8CE788DE6831205927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj2CfMKaWP9xuKjMFaTYdA/Q== X-Mailru-Sender: 689FA8AB762F73936BC43F508A0638227A96C084820BF9D316871AC359DE5621DD788429FD8613638ED9BB8B05EE7B3AFB559BB5D741EB96D19CD4E7312BAA970A04DAD6CC59E33667EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCHv2 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 comments below. On 18.02.2021 22:30, 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 > --- > @ChangeLog: Fixed -e option, when tarantool always entered interactive mode when > stdin is a tty. Now, `tarantool -e 'print"Hello"'` doesn't enter interactive mode > as it was before. > src/lib/core/errinj.h | 1 + > src/lua/init.c | 20 ++- > ...40-always-enters-interactive-mode.test.lua | 131 ++++++++++++++++++ > test/box/errinj.result | 1 + > 4 files changed, 149 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 d76aedf7a..d5fdbc209 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}) \ 1. according to name (ISATTY) variable can be in enabled or disabled state so why do you use integer type here? > > ENUM0(errinj_id, ERRINJ_LIST); > extern struct errinj errinjs[]; > diff --git a/src/lua/init.c b/src/lua/init.c > index 25e8884a6..e7e0fe006 100644 > --- a/src/lua/init.c > +++ b/src/lua/init.c > @@ -62,6 +62,7 @@ > #include "lua/swim.h" > #include "lua/decimal.h" > #include "digest.h" > +#include "errinj.h" > #include > > #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; 2. is_a_tty? > + 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..df3ee2f2d > --- /dev/null > +++ b/test/app-tap/gh-5040-always-enters-interactive-mode.test.lua > @@ -0,0 +1,131 @@ > +#!/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 testcase 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 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(#testcases) > +for _, cmd in pairs(testcases) 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() > + os.remove(output_file) > + end) > +end > + > +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