diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index 196ff583c3a..4ce8963b0be 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)