[PyQt] Disabling qFatal on unhandled exceptions

Florian Bruhin me at the-compiler.org
Thu Jul 13 18:47:12 BST 2017


Hi,

(disclaimer: I'm the one who proposed that change originally)

On Thu, Jul 13, 2017 at 10:16:55AM -0700, Luke Campagnola wrote:
> I have just discovered the change to PyQt 5.5 in which unhandled exceptions
> result in a call to qFatal(). Perhaps I am missing something important, but
> I am a confused about why this behavior was chosen. The documentation
> states that the problem with the old behavior is that "the application does
> not terminate, meaning the behaviour is different to when exceptions are
> raised in other situations". I have two concerns about this reasoning:

Because you can't cleanly exit Python when you're currently running C++
code.

> 1. Unhandled exceptions in Python do not cause the program to terminate;
> they only cause sys.excepthook to be invoked.

Same with PyQt, if you set one.

> This is the consistent, expected behavior across all event loop
> systems I have used in Python, including asyncio, tkinter, pygtk,
> tornado, twisted, gevent, PyQt4, PySide, and Python's built-in
> interactive shell.

If the framework is written in Python (without another language
involved, or with it cooperating deeply	with Python), this problem
doesn't exist. Would be interesting to know how exactly PyGTK handles
this under the hood, though.

> 2. Python should almost *never* voluntarily abort. This is one of the most
> fundamental and important differences between C++ and Python. The most
> common behavior is simply to call an error handler and move on, but even in
> situations where we are forced to end the process, it is dangerous to
> *abort* because this circumvents all of Python's shutdown machinery--files
> are not closed, destructors are not called, atexit callbacks are not
> invoked.

So what are you going to do when you're in the middle of running C++
code and there's a Python exception? You have two choices: Either call
abort(), or return *some* non-sensical value (like nullptr, or 0, or an
empty string) to Qt, and handle the exception once you're back in
Python-land.

The latter can obviously cause all kinds of funny and undefined
behavior - basically what you describe below.

> At best, this looks to the user like PyQt has caused a segfault
> (except that even fauthandler will provide no useful information).

Huh? Except the stacktrace printed by PyQt you mean?

> At worst, we can end up with corrupted files and possibly even damaged
> hardware.

abort() closes and flushes open files, but whatever buffering Python
does might indeed not be flushed.

If your hardware gets damaged because some atexit handler doesn't run
correctly, you have bigger problems...

For some more discussion about why it was introduced, see the following
threads:
https://www.riverbankcomputing.com/pipermail/pyqt/2014-September/034806.html
https://www.riverbankcomputing.com/pipermail/pyqt/2014-September/034873.html
https://www.riverbankcomputing.com/pipermail/pyqt/2014-October/034888.html

Florian

-- 
https://www.qutebrowser.org  | me at the-compiler.org (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072  | https://the-compiler.org/pubkey.asc
         I love long mails!  | https://email.is-not-s.ms/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20170713/47d5e621/attachment.sig>


More information about the PyQt mailing list