commit 61273dee395e4ba0969d93b194ab728ffb2fbc7f Author: Damian Johnson atagar@torproject.org Date: Thu Aug 11 08:49:03 2011 -0700
fix: quitting could cause unclean curses shutdown
If the user quit arm while we're processing tor events then there was a rather common timing issue where curses would terminate, then a daemon thread triggered a curses redraw. The result was that the terminal would be screwed up until the user ran 'reset'.
This was because the daemon shutdown was outside of the curses wrapper function. Changing the ordering so we shut down daemons before curses, and setting a flag during keyboard interrupts to suppress curses redraws. --- src/cli/controller.py | 11 +++++++++-- src/util/panel.py | 7 +++++-- 2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/src/cli/controller.py b/src/cli/controller.py index 8b87b1d..d2194ca 100644 --- a/src/cli/controller.py +++ b/src/cli/controller.py @@ -675,9 +675,14 @@ def startTorMonitor(startTime):
try: curses.wrapper(drawTorMonitor, startTime) - shutdownDaemons() except KeyboardInterrupt: - # skip printing stack trace in case of keyboard interrupt + # Skip printing stack trace in case of keyboard interrupt. The + # HALT_ACTIVITY attempts to prevent daemons from triggering a curses redraw + # (which would leave the user's terminal in a screwed up state). There is + # still a tiny timing issue here (after the exception but before the flag + # is set) but I've never seen it happen in practice. + + panel.HALT_ACTIVITY = True shutdownDaemons()
def drawTorMonitor(stdscr, startTime): @@ -772,4 +777,6 @@ def drawTorMonitor(stdscr, startTime): for panelImpl in displayPanels: isKeystrokeConsumed = panelImpl.handleKey(key) if isKeystrokeConsumed: break + + shutdownDaemons()
diff --git a/src/util/panel.py b/src/util/panel.py index 732610c..8a95479 100644 --- a/src/util/panel.py +++ b/src/util/panel.py @@ -25,6 +25,9 @@ for colorLabel in uiTools.COLOR_LIST: FORMAT_TAGS["<%s>" % colorLabel] = (uiTool
CONFIG = {"log.panelRecreated": log.DEBUG}
+# prevents curses redraws if set +HALT_ACTIVITY = False + def loadConfig(config): config.update(CONFIG)
@@ -375,8 +378,8 @@ class Panel(): abandoned """
- # skipped if not currently visible - if not self.isVisible(): return + # skipped if not currently visible or activity has been halted + if not self.isVisible() or HALT_ACTIVITY: return
# if the panel's completely outside its parent then this is a no-op newHeight, newWidth = self.getPreferredSize()
tor-commits@lists.torproject.org