Skip to content

Commit 50f399b

Browse files
authored
Merge pull request #30434 from anntzer/pr30426-backport-with-fix
Backport PR #30426: Fix a race condition in TexManager.make_dvi & make_png.
2 parents e9b83ef + 4c37903 commit 50f399b

File tree

1 file changed

+27
-26
lines changed

1 file changed

+27
-26
lines changed

lib/matplotlib/texmanager.py

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,9 @@ def make_dvi(cls, tex, fontsize):
276276
277277
Return the file name.
278278
"""
279-
basefile = cls.get_basefile(tex, fontsize)
280-
dvifile = '%s.dvi' % basefile
281-
if not os.path.exists(dvifile):
282-
texfile = Path(cls.make_tex(tex, fontsize))
283-
# Generate the dvi in a temporary directory to avoid race
279+
dvifile = Path(cls.get_basefile(tex, fontsize)).with_suffix(".dvi")
280+
if not dvifile.exists():
281+
# Generate the tex and dvi in a temporary directory to avoid race
284282
# conditions e.g. if multiple processes try to process the same tex
285283
# string at the same time. Having tmpdir be a subdirectory of the
286284
# final output dir ensures that they are on the same filesystem,
@@ -289,15 +287,17 @@ def make_dvi(cls, tex, fontsize):
289287
# the absolute path may contain characters (e.g. ~) that TeX does
290288
# not support; n.b. relative paths cannot traverse parents, or it
291289
# will be blocked when `openin_any = p` in texmf.cnf).
292-
cwd = Path(dvifile).parent
293-
with TemporaryDirectory(dir=cwd) as tmpdir:
294-
tmppath = Path(tmpdir)
290+
with TemporaryDirectory(dir=dvifile.parent) as tmpdir:
291+
Path(tmpdir, "file.tex").write_text(
292+
cls._get_tex_source(tex, fontsize), encoding='utf-8')
295293
cls._run_checked_subprocess(
296294
["latex", "-interaction=nonstopmode", "--halt-on-error",
297-
f"--output-directory={tmppath.name}",
298-
f"{texfile.name}"], tex, cwd=cwd)
299-
(tmppath / Path(dvifile).name).replace(dvifile)
300-
return dvifile
295+
"file.tex"], tex, cwd=tmpdir)
296+
Path(tmpdir, "file.dvi").replace(dvifile)
297+
# Also move the tex source to the main cache directory, but
298+
# only for backcompat.
299+
Path(tmpdir, "file.tex").replace(dvifile.with_suffix(".tex"))
300+
return str(dvifile)
301301

302302
@classmethod
303303
def make_png(cls, tex, fontsize, dpi):
@@ -306,22 +306,23 @@ def make_png(cls, tex, fontsize, dpi):
306306
307307
Return the file name.
308308
"""
309-
basefile = cls.get_basefile(tex, fontsize, dpi)
310-
pngfile = '%s.png' % basefile
309+
pngfile = Path(cls.get_basefile(tex, fontsize, dpi)).with_suffix(".png")
311310
# see get_rgba for a discussion of the background
312-
if not os.path.exists(pngfile):
311+
if not pngfile.exists():
313312
dvifile = cls.make_dvi(tex, fontsize)
314-
cmd = ["dvipng", "-bg", "Transparent", "-D", str(dpi),
315-
"-T", "tight", "-o", pngfile, dvifile]
316-
# When testing, disable FreeType rendering for reproducibility; but
317-
# dvipng 1.16 has a bug (fixed in f3ff241) that breaks --freetype0
318-
# mode, so for it we keep FreeType enabled; the image will be
319-
# slightly off.
320-
if (getattr(mpl, "_called_from_pytest", False) and
321-
mpl._get_executable_info("dvipng").raw_version != "1.16"):
322-
cmd.insert(1, "--freetype0")
323-
cls._run_checked_subprocess(cmd, tex)
324-
return pngfile
313+
with TemporaryDirectory(dir=pngfile.parent) as tmpdir:
314+
cmd = ["dvipng", "-bg", "Transparent", "-D", str(dpi),
315+
"-T", "tight", "-o", "file.png", dvifile]
316+
# When testing, disable FreeType rendering for reproducibility;
317+
# but dvipng 1.16 has a bug (fixed in f3ff241) that breaks
318+
# --freetype0 mode, so for it we keep FreeType enabled; the
319+
# image will be slightly off.
320+
if (getattr(mpl, "_called_from_pytest", False) and
321+
mpl._get_executable_info("dvipng").raw_version != "1.16"):
322+
cmd.insert(1, "--freetype0")
323+
cls._run_checked_subprocess(cmd, tex, cwd=tmpdir)
324+
Path(tmpdir, "file.png").replace(pngfile)
325+
return str(pngfile)
325326

326327
@classmethod
327328
def get_grey(cls, tex, fontsize=None, dpi=None):

0 commit comments

Comments
 (0)