Skip to content

Commit 64afd00

Browse files
Lazy import rlcompleter in pdb to avoid deadlock in subprocess
1 parent 20d5494 commit 64afd00

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

Lib/pdb.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@
100100
import _pyrepl.utils
101101

102102
from contextlib import ExitStack, closing, contextmanager
103-
from rlcompleter import Completer
104103
from types import CodeType
105104
from warnings import deprecated
106105

@@ -1187,6 +1186,9 @@ def completedefault(self, text, line, begidx, endidx):
11871186
return [f"${name}" for name in conv_vars if name.startswith(text[1:])]
11881187

11891188
# Use rlcompleter to do the completion
1189+
# GH-138860
1190+
# This needs to be lazy-imported to avoid deadlock
1191+
from rlcompleter import Completer
11901192
state = 0
11911193
matches = []
11921194
completer = Completer(self.curframe.f_globals | self.curframe.f_locals)
@@ -1205,6 +1207,9 @@ def _enable_rlcompleter(self, ns):
12051207

12061208
try:
12071209
old_completer = readline.get_completer()
1210+
# GH-138860
1211+
# This needs to be lazy-imported to avoid deadlock
1212+
from rlcompleter import Completer
12081213
completer = Completer(ns)
12091214
readline.set_completer(completer.complete)
12101215
yield

Lib/test/test_pdb.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4688,6 +4688,28 @@ def foo():
46884688
stdout, _ = self._run_script(script, commands)
46894689
self.assertIn("42", stdout)
46904690

4691+
def test_readline_not_imported(self):
4692+
"""GH-138860
4693+
Directly or indirectly importing readline might deadlock a subprocess
4694+
if it's launched with process_group=0 or preexec_fn=setpgrp
4695+
4696+
It's also a pattern that readline is never imported with just import pdb.
4697+
4698+
This test is to ensure that readline is not imported for import pdb.
4699+
It's possible that we have a good reason to do that in the future.
4700+
"""
4701+
4702+
script = textwrap.dedent("""
4703+
import sys
4704+
import pdb
4705+
if "readline" in sys.modules:
4706+
print("readline imported")
4707+
""")
4708+
commands = ""
4709+
stdout, stderr = self._run_script(script, commands)
4710+
self.assertNotIn("readline imported", stdout)
4711+
self.assertEqual(stderr, "")
4712+
46914713

46924714
@support.force_colorized_test_class
46934715
class PdbTestColorize(unittest.TestCase):

0 commit comments

Comments
 (0)