void-packages/srcpkgs/sagemath/patches/35195-workaround_ecl_race.p...

57 lines
2.1 KiB
Diff

diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py
index c9ca5e30939..9459cb70334 100644
--- a/src/sage/interfaces/maxima_lib.py
+++ b/src/sage/interfaces/maxima_lib.py
@@ -77,6 +77,26 @@
sage: bar == foo
True
+TESTS:
+
+Check our workaround for a race in ecl works, see :trac:`26968`.
+We use a temporary `MAXIMA_USERDIR` so it's empty; we place it
+in `DOT_SAGE` since we expect it to have more latency than `/tmp`.
+
+ sage: import tempfile, subprocess
+ sage: tmpdir = tempfile.TemporaryDirectory(dir=DOT_SAGE)
+ sage: _ = subprocess.run(['sage', '-c', # long time
+ ....: f'''
+ ....: import os
+ ....: os.environ["MAXIMA_USERDIR"] = "{tmpdir.name}"
+ ....: if not os.fork():
+ ....: import sage.interfaces.maxima_lib
+ ....: else:
+ ....: import sage.interfaces.maxima_lib
+ ....: os.wait()
+ ....: '''])
+ sage: tmpdir.cleanup()
+
"""
# ****************************************************************************
@@ -116,7 +136,23 @@
ecl_eval("(setq $nolabels t))")
ecl_eval("(defvar *MAXIMA-LANG-SUBDIR* NIL)")
ecl_eval("(set-locale-subdir)")
-ecl_eval("(set-pathnames)")
+
+try:
+ ecl_eval("(set-pathnames)")
+except RuntimeError:
+ # Recover from :trac:`26968` by creating `*maxima-objdir*` here.
+ # This cannot be done before calling `(set-pathnames)` since
+ # `*maxima-objdir*` is computed there.
+ # We use python `os.makedirs()` which is immune to the race.
+ # Using `(ensure-directories-exist ...)` in lisp would be
+ # subject to the same race condition and since `*maxima-objdir*`
+ # has multiple components this is quite plausible to happen.
+ maxima_objdir = ecl_eval("*maxima-objdir*").python()[1:-1]
+ import os
+ os.makedirs(maxima_objdir, exist_ok=True)
+ # Call `(set-pathnames)` again to complete its job.
+ ecl_eval("(set-pathnames)")
+
ecl_eval("(defun add-lineinfo (x) x)")
ecl_eval('(defun principal nil (cond ($noprincipal (diverg)) ((not pcprntd) (merror "Divergent Integral"))))')
ecl_eval("(remprop 'mfactorial 'grind)") # don't use ! for factorials (#11539)