| 327 | |
| 328 | @pytest.mark.backend('QtAgg', skip_on_importerror=True) |
| 329 | def test_fig_sigint_override(): |
| 330 | from matplotlib.backends.backend_qt5 import _BackendQT5 |
| 331 | # Create a figure |
| 332 | plt.figure() |
| 333 | |
| 334 | # Variable to access the handler from the inside of the event loop |
| 335 | event_loop_handler = None |
| 336 | |
| 337 | # Callback to fire during event loop: save SIGINT handler, then exit |
| 338 | def fire_signal_and_quit(): |
| 339 | # Save event loop signal |
| 340 | nonlocal event_loop_handler |
| 341 | event_loop_handler = signal.getsignal(signal.SIGINT) |
| 342 | |
| 343 | # Request event loop exit |
| 344 | QtCore.QCoreApplication.exit() |
| 345 | |
| 346 | # Timer to exit event loop |
| 347 | QtCore.QTimer.singleShot(0, fire_signal_and_quit) |
| 348 | |
| 349 | # Save original SIGINT handler |
| 350 | original_handler = signal.getsignal(signal.SIGINT) |
| 351 | |
| 352 | # Use our own SIGINT handler to be 100% sure this is working |
| 353 | def custom_handler(signum, frame): |
| 354 | pass |
| 355 | |
| 356 | signal.signal(signal.SIGINT, custom_handler) |
| 357 | |
| 358 | try: |
| 359 | # mainloop() sets SIGINT, starts Qt event loop (which triggers timer |
| 360 | # and exits) and then mainloop() resets SIGINT |
| 361 | matplotlib.backends.backend_qt._BackendQT.mainloop() |
| 362 | |
| 363 | # Assert: signal handler during loop execution is changed |
| 364 | # (can't test equality with func) |
| 365 | assert event_loop_handler != custom_handler |
| 366 | |
| 367 | # Assert: current signal handler is the same as the one we set before |
| 368 | assert signal.getsignal(signal.SIGINT) == custom_handler |
| 369 | |
| 370 | # Repeat again to test that SIG_DFL and SIG_IGN will not be overridden |
| 371 | for custom_handler in (signal.SIG_DFL, signal.SIG_IGN): |
| 372 | QtCore.QTimer.singleShot(0, fire_signal_and_quit) |
| 373 | signal.signal(signal.SIGINT, custom_handler) |
| 374 | |
| 375 | _BackendQT5.mainloop() |
| 376 | |
| 377 | assert event_loop_handler == custom_handler |
| 378 | assert signal.getsignal(signal.SIGINT) == custom_handler |
| 379 | |
| 380 | finally: |
| 381 | # Reset SIGINT handler to what it was before the test |
| 382 | signal.signal(signal.SIGINT, original_handler) |
| 383 | |
| 384 | |
| 385 | @pytest.mark.backend('QtAgg', skip_on_importerror=True) |