You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by ta...@apache.org on 2020/04/30 19:21:28 UTC
[impala] branch master updated: IMPALA-9398: Fix shell history
duplication when cmdloop breaks
This is an automated email from the ASF dual-hosted git repository.
tarmstrong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git
The following commit(s) were added to refs/heads/master by this push:
new 1a36a03 IMPALA-9398: Fix shell history duplication when cmdloop breaks
1a36a03 is described below
commit 1a36a0348b85c2b2008d7b4b3a061a467f8456e7
Author: Tamas Mate <tm...@cloudera.com>
AuthorDate: Mon Mar 2 16:13:53 2020 +0100
IMPALA-9398: Fix shell history duplication when cmdloop breaks
This change adds a new condition to avoid re-reading the impala-shell
history when the cmdloop is broken. The loop can break due to exceptions
such as KeyboardInterrupt.
Testing:
- The change was tested manually on local dev env
- Added a new EE shell test to verify the history after SIGINT
Change-Id: If4faf46134f44d91e56748642f47d448707db53c
Reviewed-on: http://gerrit.cloudera.org:8080/15345
Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
shell/impala_shell.py | 32 +++++++++++++++-----------------
tests/shell/test_shell_interactive.py | 33 +++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+), 17 deletions(-)
diff --git a/shell/impala_shell.py b/shell/impala_shell.py
index 549cd71..8c877d1 100755
--- a/shell/impala_shell.py
+++ b/shell/impala_shell.py
@@ -230,11 +230,25 @@ class ImpalaShell(cmd.Cmd, object):
self.readline = __import__('readline')
try:
self.readline.set_history_length(int(options.history_max))
+ # The history file is created when the Impala shell is invoked and commands are
+ # issued. In case it does not exist do not read the history file.
+ if os.path.exists(self.history_file):
+ self.readline.read_history_file(self.history_file)
+ self._replace_history_delimiters(ImpalaShell.HISTORY_FILE_QUERY_DELIM, '\n')
except ValueError:
warning = "WARNING: history_max option malformed %s\n" % options.history_max
print(warning, file=sys.stderr)
self.readline.set_history_length(1000)
- except ImportError:
+ except IOError, i:
+ warning = "WARNING: Unable to load command history (disabling impala-shell " \
+ "command history): %s" % i
+ print(warning, file=sys.stderr)
+ # This history file exists but is not readable, disable readline.
+ self._disable_readline()
+ except ImportError, i:
+ warning = "WARNING: Unable to import readline module (disabling impala-shell " \
+ "command history): %s" % i
+ print(warning, file=sys.stderr)
self._disable_readline()
if options.impalad is not None:
@@ -1372,22 +1386,6 @@ class ImpalaShell(cmd.Cmd, object):
else:
return CmdStatus.ERROR
- def preloop(self):
- """Load the history file if it exists"""
- if self.readline:
- # The history file is created when the Impala shell is invoked and commands are
- # issued. In the first invocation of the shell, the history file will not exist.
- # Clearly, this is not an error, return.
- if not os.path.exists(self.history_file): return
- try:
- self.readline.read_history_file(self.history_file)
- self._replace_history_delimiters(ImpalaShell.HISTORY_FILE_QUERY_DELIM, '\n')
- except IOError as i:
- msg = "Unable to load command history (disabling history collection): %s" % i
- print(msg, file=sys.stderr)
- # This history file exists but is not readable, disable readline.
- self._disable_readline()
-
def postloop(self):
"""Save session commands in history."""
if self.readline:
diff --git a/tests/shell/test_shell_interactive.py b/tests/shell/test_shell_interactive.py
index ceee1fd..27dc4bd 100755
--- a/tests/shell/test_shell_interactive.py
+++ b/tests/shell/test_shell_interactive.py
@@ -446,6 +446,39 @@ class TestImpalaShellInteractive(ImpalaTestSuite):
assert history_entry in result.stderr, "'%s' not in '%s'" % (history_entry,
result.stderr)
+ def test_history_does_not_duplicate_on_interrupt(self, vector, tmp_history_file):
+ """This test verifies that once the cmdloop is broken the history file will not be
+ re-read. The cmdloop can be broken when the user sends a SIGINT or exceptions
+ occur."""
+ # readline gets its input from tty, so using stdin does not work.
+ shell_cmd = get_shell_cmd(vector)
+ child_proc = pexpect.spawn(shell_cmd[0], shell_cmd[1:])
+ # set up history
+ child_proc.expect(PROMPT_REGEX)
+ child_proc.sendline("select 1;")
+ child_proc.expect("Fetched 1 row\(s\) in [0-9]+\.?[0-9]*s")
+ child_proc.expect(PROMPT_REGEX)
+ child_proc.sendline("quit;")
+ child_proc.wait()
+ child_proc = pexpect.spawn(shell_cmd[0], shell_cmd[1:])
+ child_proc.expect(PROMPT_REGEX)
+
+ # send SIGINT then quit to save history
+ child_proc.sendintr()
+ child_proc.sendline("select 2;")
+ child_proc.expect("Fetched 1 row\(s\) in [0-9]+\.?[0-9]*s")
+ child_proc.sendline("quit;")
+ child_proc.wait()
+
+ # check history in a new instance
+ p = ImpalaShell(vector)
+ p.send_cmd('history')
+ result = p.get_result().stderr.splitlines()
+ assert "[1]: select 1;" == result[1]
+ assert "[2]: quit;" == result[2]
+ assert "[3]: select 2;" == result[3]
+ assert "[4]: quit;" == result[4]
+
def test_history_file_option(self, vector, tmp_history_file):
"""
Setting the 'tmp_history_file' fixture above means that the IMPALA_HISTFILE