Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
When programming plugins, it's easy to write code that terminates in a fatal error if something goes wrong. Indeed, plugins might even assume that any exceptions they raise will be handled by Plover. But Qt GUI code isn't necessarily this way, since it executes one level above the engine. A GUI tool plugin that raises an exception during dialog creation, for instance, will propagate it back to
MainWindow._activate_dialog
, which was called by a Qt signal on clicking the toolbar button. When that exception escapes, the engine will never see it, and Plover will crash without warning.In fact, any exception that escapes a PyQt slot will have this effect by default. Any time a slot is called from a signal, that method is the bottom of the stack as far as Python can see. If an exception escapes and
sys.excepthook
is not defined, Plover just crashes, but if it is defined, it executes and the event loop resumes. I have defined this function to provide a default safety net by logging any such exception as an error.A system-wide exception hook may seem a little heavy-handed, but it's the only way to reliably catch stuff originating from arbitrary GUI plugins. The engine will still catch everything it would have caught normally; this function is only called if an exception sidesteps the engine's normal flow control by going through a Qt slot. Some debuggers like to override this hook themselves, so the hook only activates if nothing has messed with it (i.e. it is still the original value,
sys.__excepthook__
). Naturally, it is difficult to write tests for something this broad, but deleting random characters out of various pieces of GUI code seems to trigger it and log the error now where it would have killed Plover before. It's not something that's supposed to be executed under normal conditions in any case; it's a last resort to stop bugs in signal-based GUI code from bringing down the whole system.Summary of changes