Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-123856: Fix PyREPL failure when a keyboard interrupt is triggered after using a history search #124396

Merged

Conversation

emilyemorehouse
Copy link
Member

@emilyemorehouse emilyemorehouse commented Sep 23, 2024

The original check in Lib/_pyrepl/simple_interact.py for handling the manual clean up when a KeyboardInterrupt is received would result in duplicate calls to clean up the search translator in some scenarios. When the search translator is allowed to exit cleanly without a KeyboardInterrupt, it calls its clean-up function (isearch_end) on its own. If a KeyboardInterrupt was triggered immediately after, the most recent command was still isearch, which would trigger a similar clean-up routine incorrectly. This now ensures that the clean-up is only executed once.

I've also added tests – we had to make modifications to the way the full version of the REPL is run – this now allows the necessary control characters to pass through. Additional overrides for other control characters may be required here as the test suite is bolstered.

Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I confirm that this change fix #123856. The fix works with forward and backward isearch.

Moreover, CTRL+C in an interactive search (CTRL+S or CTRL+R) still resets the prompt to >>> as expected.

Using r.isearch_trans looks safe to me since r is created by _ReadlineWrapper.get_reader() which returns a ReadlineAlikeReader and ReadlineAlikeReader inherits from HistoricalReader.

@emilyemorehouse
Copy link
Member Author

@vstinner thanks for reviewing the draft version of this - I refactored the clean-up process to better mimic what happens when the search is allowed to clean up after itself (see the PR description for a little more info)

@emilyemorehouse emilyemorehouse force-pushed the bug/gh-123856-pyrepl-search-ctrl-c-fail branch from 5bf83d6 to 7389752 Compare September 24, 2024 18:40
Copy link
Member

@vstinner vstinner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The fix still works as expected. I tried different scenario and it just works.

I just have minor comments on the test, you can ignore them.

@@ -1305,3 +1312,7 @@ def test_readline_history_file(self):
output, exit_code = self.run_repl("exit\n", env=env)
self.assertEqual(exit_code, 0)
self.assertNotIn("\\040", pathlib.Path(hfile.name).read_text())

def test_keyboard_interrupt_after_isearch(self):
output, exit_code = self.run_repl(["\x12", "\x03", "exit"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to add (module-level) constants for "\x12" and "\x03"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll do that later as part of more tests for control characters.

@@ -1246,6 +1247,12 @@ def _run_repl(
env["PYTHON_HISTORY"] = os.path.join(cwd, ".regrtest_history")
if cmdline_args is not None:
cmd.extend(cmdline_args)

term_attr = termios.tcgetattr(slave_fd)
term_attr[6][termios.VREPRINT] = 0 # pass through CTRL-R
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the hardcoded constant 6?

@ambv
Copy link
Contributor

ambv commented Sep 24, 2024

Address sanitizer is failing test_pyrepl with:

warning: can't use pyrepl: setupterm: could not find terminfo database

@ambv
Copy link
Contributor

ambv commented Sep 25, 2024

After trying to find which TERM's on address sanitizer, we're still seeing

warning: can't use pyrepl: setupterm: could not find terminfo database

which suggests TERM is unset or empty. Let's just add that case to our TestMain ignore.

Copy link
Contributor

@ambv ambv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent!

@@ -1305,3 +1312,7 @@ def test_readline_history_file(self):
output, exit_code = self.run_repl("exit\n", env=env)
self.assertEqual(exit_code, 0)
self.assertNotIn("\\040", pathlib.Path(hfile.name).read_text())

def test_keyboard_interrupt_after_isearch(self):
output, exit_code = self.run_repl(["\x12", "\x03", "exit"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll do that later as part of more tests for control characters.

Comment on lines +165 to +166
if r.input_trans is r.isearch_trans:
r.do_cmd(("isearch-end", [""]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads much better 👍🏻

@ambv ambv merged commit c1600c7 into python:main Sep 25, 2024
42 checks passed
@miss-islington-app
Copy link

Thanks @emilyemorehouse for the PR, and @ambv for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Sep 25, 2024
…gered after using a history search (pythonGH-124396)

(cherry picked from commit c1600c7)

Co-authored-by: Emily Morehouse <emily@cuttlesoft.com>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
@bedevere-app
Copy link

bedevere-app bot commented Sep 25, 2024

GH-124530 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.13 bugs and security fixes label Sep 25, 2024
Yhg1s pushed a commit that referenced this pull request Sep 26, 2024
…ggered after using a history search (GH-124396) (#124530)

gh-123856: Fix PyREPL failure when a keyboard interrupt is triggered after using a history search (GH-124396)
(cherry picked from commit c1600c7)

Co-authored-by: Emily Morehouse <emily@cuttlesoft.com>
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants