Skip to content

Commit ba483b0

Browse files
committed
monkeypatch _mathtext.Parser.parse() with a threading.Lock()
This is to prevent concurrent corruption of the parser singleton's mutable state.
1 parent 36ae86d commit ba483b0

1 file changed

Lines changed: 24 additions & 0 deletions

File tree

ipympl/backend_nbagg.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,30 @@
6060

6161
from ._version import js_semver
6262

63+
# Workaround for thread-safety issues in matplotlib's mathtext parser.
64+
# The _mathtext.Parser singleton has mutable state (_state_stack, etc.) that is
65+
# not protected against concurrent access from multiple threads. When ipympl is
66+
# used with ipykernel >= 7 (which introduces additional threads for message
67+
# routing), concurrent calls to the parser can corrupt this state, leading to
68+
# ParseException errors like 'Expected end of text, found "$"'.
69+
# See https://github.com/matplotlib/ipympl/issues/610
70+
try:
71+
import functools
72+
73+
from matplotlib._mathtext import Parser as _MathTextInternalParser
74+
75+
_mathtext_parse_lock = Lock()
76+
_original_mathtext_parse = _MathTextInternalParser.parse
77+
78+
@functools.wraps(_original_mathtext_parse)
79+
def _thread_safe_mathtext_parse(self, *args, **kwargs):
80+
with _mathtext_parse_lock:
81+
return _original_mathtext_parse(self, *args, **kwargs)
82+
83+
_MathTextInternalParser.parse = _thread_safe_mathtext_parse
84+
except Exception:
85+
pass
86+
6387
cursors_str = {
6488
cursors.HAND: 'pointer',
6589
cursors.POINTER: 'default',

0 commit comments

Comments
 (0)