Skip to content

Commit

Permalink
Fixed issue where persistent history file was not saved upon SIGTERM …
Browse files Browse the repository at this point in the history
…and SIGHUP signals.
  • Loading branch information
kmvanbrunt committed Sep 12, 2024
1 parent be15939 commit 673eec3
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ def unregister_command_set(self, cmdset: CommandSet) -> None:

methods = inspect.getmembers(
cmdset,
predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type, var-annotated]
and hasattr(meth, '__name__')
and meth.__name__.startswith(COMMAND_FUNC_PREFIX),
)
Expand Down Expand Up @@ -811,7 +811,7 @@ def unregister_command_set(self, cmdset: CommandSet) -> None:
def _check_uninstallable(self, cmdset: CommandSet) -> None:
methods = inspect.getmembers(
cmdset,
predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type]
predicate=lambda meth: isinstance(meth, Callable) # type: ignore[arg-type, var-annotated]
and hasattr(meth, '__name__')
and meth.__name__.startswith(COMMAND_FUNC_PREFIX),
)
Expand Down Expand Up @@ -2418,7 +2418,7 @@ def get_help_topics(self) -> List[str]:
def sigint_handler(self, signum: int, _: FrameType) -> None:
"""Signal handler for SIGINTs which typically come from Ctrl-C events.
If you need custom SIGINT behavior, then override this function.
If you need custom SIGINT behavior, then override this method.
:param signum: signal number
:param _: required param for signal handlers
Expand All @@ -2437,6 +2437,30 @@ def sigint_handler(self, signum: int, _: FrameType) -> None:
if raise_interrupt:
self._raise_keyboard_interrupt()

def sigterm_handler(self, signum: int, _: FrameType) -> None:
"""
Signal handler for SIGTERMs which are sent to politely ask this app to terminate.
If you need custom SIGTERM behavior, then override this method.
:param signum: signal number
:param _: required param for signal handlers
"""
# Gracefully exit so the persistent history file will be written.
sys.exit(self.exit_code)

def sighup_handler(self, signum: int, _: FrameType) -> None:
"""
Signal handler for SIGHUPs which are sent when the terminal is closed.
If you need custom SIGHUP behavior, then override this method.
:param signum: signal number
:param _: required param for signal handlers
"""
# Gracefully exit so the persistent history file will be written.
sys.exit(self.exit_code)

def _raise_keyboard_interrupt(self) -> None:
"""Helper function to raise a KeyboardInterrupt"""
raise KeyboardInterrupt("Got a keyboard interrupt")
Expand Down Expand Up @@ -5447,6 +5471,12 @@ def cmdloop(self, intro: Optional[str] = None) -> int: # type: ignore[override]
original_sigint_handler = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, self.sigint_handler) # type: ignore

original_sigterm_handler = signal.getsignal(signal.SIGTERM)
signal.signal(signal.SIGTERM, self.sigterm_handler) # type: ignore

original_sighup_handler = signal.getsignal(signal.SIGHUP)
signal.signal(signal.SIGHUP, self.sighup_handler) # type: ignore

# Grab terminal lock before the command line prompt has been drawn by readline
self.terminal_lock.acquire()

Expand Down Expand Up @@ -5479,8 +5509,10 @@ def cmdloop(self, intro: Optional[str] = None) -> int: # type: ignore[override]
# This will also zero the lock count in case cmdloop() is called again
self.terminal_lock.release()

# Restore the original signal handler
# Restore the original signal handlers
signal.signal(signal.SIGINT, original_sigint_handler)
signal.signal(signal.SIGTERM, original_sigterm_handler)
signal.signal(signal.SIGHUP, original_sighup_handler)

return self.exit_code

Expand Down

0 comments on commit 673eec3

Please sign in to comment.