8000 Merge pull request #17839 from anntzer/unlock · matplotlib/matplotlib@e2d0fa2 · GitHub
[go: up one dir, main page]

Skip to content

Commit e2d0fa2

Browse files
authored
Merge pull request #17839 from anntzer/unlock
MNT: Avoid need to lock in dvi generation, to avoid deadlocks.
2 parents 61c0d4a + 0efc44c commit e2d0fa2

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

lib/matplotlib/texmanager.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from pathlib import Path
3636
import re
3737
import subprocess
38+
from tempfile import TemporaryDirectory
3839

3940
import numpy as np
4041

@@ -269,12 +270,12 @@ def make_tex_preview(self, tex, fontsize):
269270

270271
return texfile
271272

272-
def _run_checked_subprocess(self, command, tex):
273+
def _run_checked_subprocess(self, command, tex, *, cwd=None):
273274
_log.debug(cbook._pformat_subprocess(command))
274275
try:
275-
report = subprocess.check_output(command,
276-
cwd=self.texcache,
277-
stderr=subprocess.STDOUT)
276+
report = subprocess.check_output(
277+
command, cwd=cwd if cwd is not None else self.texcache,
278+
stderr=subprocess.STDOUT)
278279
except FileNotFoundError as exc:
279280
raise RuntimeError(
280281
'Failed to process string with tex because {} could not be '
@@ -305,17 +306,16 @@ def make_dvi(self, tex, fontsize):
305306
dvifile = '%s.dvi' % basefile
306307
if not os.path.exists(dvifile):
307308
texfile = self.make_tex(tex, fontsize)
308-
with cbook._lock_path(texfile):
309+
# Generate the dvi in a temporary directory to avoid race
310+
# conditions e.g. if multiple processes try to process the same tex
311+
# string at the same time. Having tmpdir be a subdirectory of the
312+
# final output dir ensures that they are on the same filesystem,
313+
# and thus replace() works atomically.
314+
with TemporaryDirectory(dir=Path(dvifile).parent) as tmpdir:
309315
self._run_checked_subprocess(
310316
["latex", "-interaction=nonstopmode", "--halt-on-error",
311-
texfile], tex)
312-
for fname in glob.glob(basefile + '*'):
313-
if not fname.endswith(('dvi', 'tex')):
314-
try:
315-
os.remove(fname)
316-
except OSError:
317-
pass
318-
317+
texfile], tex, cwd=tmpdir)
318+
(Path(tmpdir) / Path(dvifile).name).replace(dvifile)
319319
return dvifile
320320

321321
@cbook.deprecated("3.3")

0 commit comments

Comments
 (0)
0