@@ -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