Skip to content

Commit 500e6fd

Browse files
ENH: webagg: Handle ioloop shutdown correctly
This change correctly cleans up after the ioloop is interrupted, allowing the user to call plt.show(), then resume control with a SIGINT, then call plt.show() again.
1 parent 35e2781 commit 500e6fd

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

lib/matplotlib/backends/backend_webagg.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515

1616
from matplotlib.externals import six
1717

18-
import datetime
1918
import errno
2019
import json
2120
import os
2221
import random
2322
import sys
23+
import signal
2424
import socket
2525
import threading
26+
from contextlib import contextmanager
2627

2728
try:
2829
import tornado
@@ -323,26 +324,39 @@ def start(cls):
323324
if cls.started:
324325
return
325326

326-
# Set the flag to True *before* blocking on IOLoop.instance().start()
327-
cls.started = True
328-
329327
"""
330328
IOLoop.running() was removed as of Tornado 2.4; see for example
331329
https://groups.google.com/forum/#!topic/python-tornado/QLMzkpQBGOY
332330
Thus there is no correct way to check if the loop has already been
333331
launched. We may end up with two concurrently running loops in that
334332
unlucky case with all the expected consequences.
335333
"""
336-
print("Press Ctrl+C to stop WebAgg server")
337-
sys.stdout.flush()
338-
try:
339-
tornado.ioloop.IOLoop.instance().start()
340-
except KeyboardInterrupt:
334+
ioloop = tornado.ioloop.IOLoop.instance()
335+
336+
def shutdown():
337+
ioloop.stop()
341338
print("Server is stopped")
342339
sys.stdout.flush()
343-
finally:
344340
cls.started = False
345341

342+
@contextmanager
343+
def catch_sigint():
344+
old_handler = signal.signal(
345+
signal.SIGINT,
346+
lambda sig, frame: ioloop.add_callback_from_signal(shutdown))
347+
try:
348+
yield
349+
finally:
350+
signal.signal(signal.SIGINT, old_handler)
351+
352+
# Set the flag to True *before* blocking on ioloop.start()
353+
cls.started = True
354+
355+
print("Press Ctrl+C to stop WebAgg server")
356+
sys.stdout.flush()
357+
with catch_sigint():
358+
ioloop.start()
359+
346360

347361
def ipython_inline_display(figure):
348362
import tornado.template

0 commit comments

Comments
 (0)