You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Right now, our methods related to event loops and timers have inconsistent behavior across interactive backends. When called on a worker thread, or when called in a specific order, these methods will often raise internal errors from the wrapped GUI framework. In several cases, they will crash the process entirely.
The exact behavior can vary depending on platform. For example, pyplot.show() on a worker thread crashes in GTK+macOS, but works in GTK+Linux as long as you are very careful.
Proposed fix
I propose that we unify the behavior across all interactive backends by raising an error when the following are called on a worker thread:
plt.show() FigureCanvas.start_event_loop() FigureCanvas.stop_event_loop() FigureCanvas.flush_events() FigureCanvas.new_timer()
Any method of Timer (note: backends could still use Timers internally as needed)
Additionally, for consistency:
plt.show() and FigureCanvas.start_event_loop() should raise an error if an event loop is already running - this matches the existing behavior of most backends.
FigureCanvas.stop_event_loop() should stop the event loop if it is running, regardless of how that event loop was started. If an event loop isn't running, it should simply return (the existing behavior of most backends).
All of the changes in Timer consistency across backends #29062. I'm still auditing Timer behavior across backends - I believe that there are cases that this PR doesn't yet cover.
For now, we could add a deprecation message if the behavior doesn't already raise or crash. For behavior that currently crashes, I'm not sure of our policy. Would we print a deprecation message and then crash? Or would we raise an error now without a deprecation cycle?
Summary
Right now, our methods related to event loops and timers have inconsistent behavior across interactive backends. When called on a worker thread, or when called in a specific order, these methods will often raise internal errors from the wrapped GUI framework. In several cases, they will crash the process entirely.
The exact behavior can vary depending on platform. For example,
pyplot.show()on a worker thread crashes in GTK+macOS, but works in GTK+Linux as long as you are very careful.Proposed fix
I propose that we unify the behavior across all interactive backends by raising an error when the following are called on a worker thread:
plt.show()FigureCanvas.start_event_loop()FigureCanvas.stop_event_loop()FigureCanvas.flush_events()FigureCanvas.new_timer()Any method of
Timer(note: backends could still use Timers internally as needed)Additionally, for consistency:
plt.show()andFigureCanvas.start_event_loop()should raise an error if an event loop is already running - this matches the existing behavior of most backends.FigureCanvas.stop_event_loop()should stop the event loop if it is running, regardless of how that event loop was started. If an event loop isn't running, it should simply return (the existing behavior of most backends).For now, we could add a deprecation message if the behavior doesn't already raise or crash. For behavior that currently crashes, I'm not sure of our policy. Would we print a deprecation message and then crash? Or would we raise an error now without a deprecation cycle?
Related issues: #31858, #31968