From c7f386cec0f2de3e4cb64b53b064576494ac711d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 18 Nov 2015 20:21:23 +0100 Subject: [PATCH] Avoid logging in signal handlers. If we don't do that, we can get this: --- Logging error --- Traceback (most recent call last): File ".../python3.5/logging/__init__.py", line 984, in emit self.flush() File ".../python3.5/logging/__init__.py", line 964, in flush self.stream.flush() RuntimeError: reentrant call inside <_io.BufferedWriter name=''> Call stack: [...] File ".../qutebrowser/app.py", line 122, in qt_mainloop return qApp.exec_() File ".../qutebrowser/utils/objreg.py", line 118, in on_destroyed log.destroy.debug("schedule removal: {}".format(name)) File ".../python3.5/logging/__init__.py", line 1267, in debug self._log(DEBUG, msg, args, **kwargs) File ".../python3.5/logging/__init__.py", line 1415, in _log self.handle(record) File ".../python3.5/logging/__init__.py", line 1425, in handle self.callHandlers(record) File ".../python3.5/logging/__init__.py", line 1487, in callHandlers hdlr.handle(record) File ".../python3.5/logging/__init__.py", line 855, in handle self.emit(record) File ".../python3.5/logging/__init__.py", line 984, in emit self.flush() File ".../python3.5/logging/__init__.py", line 964, in flush self.stream.flush() File ".../qutebrowser/misc/crashsignal.py", line 365, in interrupt log.destroy.info("Do the same again to forcefully quit.") Message: 'Do the same again to forcefully quit.' Arguments: () --- qutebrowser/misc/crashsignal.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/qutebrowser/misc/crashsignal.py b/qutebrowser/misc/crashsignal.py index 98a74b666..940d23de2 100644 --- a/qutebrowser/misc/crashsignal.py +++ b/qutebrowser/misc/crashsignal.py @@ -355,17 +355,23 @@ class SignalHandler(QObject): log.destroy.exception("Failed to read wakeup fd.") self._notifier.setEnabled(True) + def _log_later(self, *lines): + """Log the given text line-wise with a QTimer.""" + for line in lines: + QTimer.singleShot(0, functools.partial(log.destroy.info, line)) + def interrupt(self, signum, _frame): """Handler for signals to gracefully shutdown (SIGINT/SIGTERM). This calls shutdown and remaps the signal to call interrupt_forcefully the next time. """ - log.destroy.info("SIGINT/SIGTERM received, shutting down!") - log.destroy.info("Do the same again to forcefully quit.") signal.signal(signal.SIGINT, self.interrupt_forcefully) signal.signal(signal.SIGTERM, self.interrupt_forcefully) - # If we call shutdown directly here, we get a segfault. + # Signals can arrive anywhere, so we do this in the main thread + self._log_later( + "SIGINT/SIGTERM received, shutting down!", + "Do the same again to forcefully quit.") QTimer.singleShot(0, functools.partial( self._quitter.shutdown, 128 + signum)) @@ -376,12 +382,12 @@ class SignalHandler(QObject): It then remaps the signals to call self.interrupt_really_forcefully the next time. """ - log.destroy.info("Forceful quit requested, goodbye cruel world!") - log.destroy.info("Do the same again to quit with even more force.") signal.signal(signal.SIGINT, self.interrupt_really_forcefully) signal.signal(signal.SIGTERM, self.interrupt_really_forcefully) - # This *should* work without a QTimer, but because of the trouble in - # self.interrupt we're better safe than sorry. + # Signals can arrive anywhere, so we do this in the main thread + self._log_later( + "Forceful quit requested, goodbye cruel world!", + "Do the same again to quit with even more force.") QTimer.singleShot(0, functools.partial(self._app.exit, 128 + signum)) def interrupt_really_forcefully(self, signum, _frame): @@ -390,5 +396,5 @@ class SignalHandler(QObject): This doesn't run *any* Qt cleanup and simply exits via Python. It will most likely lead to a segfault. """ - log.destroy.info("WHY ARE YOU DOING THIS TO ME? :(") + print("WHY ARE YOU DOING THIS TO ME? :(") sys.exit(128 + signum)