Skip to content

Commit ed09d58

Browse files
committed
Don't allow built-in cmdloop to run outside of main thread
1 parent 41e6430 commit ed09d58

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

cmd2/cmd2.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,6 +3855,16 @@ def cmdloop(self, intro: Optional[str] = None) -> None:
38553855
38563856
:param intro: if provided this overrides self.intro and serves as the intro banner printed once at start
38573857
"""
3858+
# cmdloop() expects to be run in the main thread to support extensive use of KeyboardInterrupts throughout the
3859+
# other built-in functions. You are free to override cmdloop, but much of cmd2's features will be limited.
3860+
if not threading.current_thread() is threading.main_thread():
3861+
raise RuntimeError("cmdloop must be run in the main thread")
3862+
3863+
# Register a SIGINT signal handler for Ctrl+C
3864+
import signal
3865+
original_sigint_handler = signal.getsignal(signal.SIGINT)
3866+
signal.signal(signal.SIGINT, self.sigint_handler)
3867+
38583868
if self.allow_cli_args:
38593869
parser = argparse.ArgumentParser()
38603870
parser.add_argument('-t', '--test', action="store_true",
@@ -3908,9 +3918,8 @@ def cmdloop(self, intro: Optional[str] = None) -> None:
39083918
# This will also zero the lock count in case cmdloop() is called again
39093919
self.terminal_lock.release()
39103920

3911-
if threading.current_thread() is threading.main_thread():
3912-
# Restore the original signal handler
3913-
signal.signal(signal.SIGINT, original_sigint_handler)
3921+
# Restore the original signal handler
3922+
signal.signal(signal.SIGINT, original_sigint_handler)
39143923

39153924
if self.exit_code is not None:
39163925
sys.exit(self.exit_code)

0 commit comments

Comments
 (0)