Ticket #14242: 14242_gap_workspace_race.patch

File 14242_gap_workspace_race.patch, 4.6 KB (added by jdemeyer, 7 years ago)
  • sage/interfaces/gap.py

    # HG changeset patch
    # User Jeroen Demeyer <jdemeyer@cage.ugent.be>
    # Date 1362667188 -3600
    # Node ID c0ae228090592c3d0346677a682e910e5c215873
    # Parent  e281b0f00aa75bb7618d7a3a503286d8af88e892
    Race condition in gap_reset_workspace()
    
    diff --git a/sage/interfaces/gap.py b/sage/interfaces/gap.py
    a b  
    708708            sage: rc = gap.interrupt(timeout=1)
    709709            sage: gap._eval_using_file_cutoff = cutoff
    710710
    711         The following tests against a bug fixed at trac ticket #10296:
     711        The following tests against a bug fixed at :trac:`10296`::
    712712
    713713            sage: gap(3)
    714714            3
     
    11731173            Expect._start(self, "Failed to start GAP.")
    11741174        except Exception:
    11751175            if self.__use_workspace_cache and first_try:
    1176                 print "A workspace appears to have been corrupted... automatically rebuilding (this is harmless)."
    11771176                first_try = False
    11781177                self.quit(timeout=0)
    11791178                expect.failed_to_start.remove(self.name())
    11801179                gap_reset_workspace(verbose=False)
    11811180                Expect._start(self, "Failed to start GAP.")
    11821181                self._session_number = n
    1183                 return
    1184             raise
     1182                self.__make_workspace = False
     1183            else:
     1184                raise
    11851185       
    11861186        if self.__use_workspace_cache and self.__make_workspace:
    11871187            self.save_workspace()
     
    12531253        # SaveWorkspace can only be used at the main gap> prompt. It cannot
    12541254        # be included in the body of a loop or function, or called from a
    12551255        # break loop.
    1256         self.eval('SaveWorkspace("%s");'%WORKSPACE, allow_use_file=False)
     1256
     1257        # Save the worksheet to a temporary file and then move that
     1258        # file in place to avoid race conditions.
     1259        WORKSPACE_TMP = "%s-%s"%(WORKSPACE, self.pid())
     1260        self.eval('SaveWorkspace("%s");'%WORKSPACE_TMP, allow_use_file=False)
     1261        try:
     1262            os.rename(WORKSPACE_TMP, WORKSPACE)
     1263        except OSError:
     1264            # Some operating systems might not support in-place
     1265            # renaming. We delete the original file first.
     1266            os.unlink(WORKSPACE)
     1267            os.rename(WORKSPACE_TMP, WORKSPACE)
    12571268
    12581269    # Todo -- this -- but there is a tricky "when does it end" issue!
    12591270    # Maybe do via a file somehow?
     
    14341445    default when Sage first starts GAP.
    14351446   
    14361447    The first time you start GAP from Sage, it saves the startup state
    1437     of GAP in the file
    1438    
    1439     ::
    1440    
    1441                 $HOME/.sage/gap-workspace
    1442            
     1448    of GAP in a file ``$HOME/.sage/gap/workspace-HASH``, where ``HASH``
     1449    is a hash of the directory where Sage is installed.
    14431450   
    14441451    This is useful, since then subsequent startup of GAP is at least 10
    14451452    times as fast. Unfortunately, if you install any new code for GAP,
     
    14491456    The packages sonata, guava, factint, gapdoc, grape, design, toric,
    14501457    and laguna are loaded in all cases before the workspace is saved,
    14511458    if they are available.
     1459
     1460    TESTS:
     1461
     1462    Check that the race condition from :trac:`14242` has been fixed.
     1463    We temporarily need to change the worksheet filename. ::
     1464
     1465        sage: ORIGINAL_WORKSPACE = sage.interfaces.gap.WORKSPACE
     1466        sage: sage.interfaces.gap.WORKSPACE = tmp_filename()
     1467        sage: from multiprocessing import Process
     1468        sage: import time
     1469        sage: gap = Gap()  # long time (reset GAP session)
     1470        sage: P = [Process(target=gap, args=("14242",)) for i in range(4)]
     1471        sage: for p in P:  # long time, indirect doctest
     1472        ...       p.start()
     1473        ...       time.sleep(0.2)
     1474        sage: for p in P:  # long time
     1475        ...       p.join()
     1476        sage: os.unlink(sage.interfaces.gap.WORKSPACE)  # long time
     1477        sage: sage.interfaces.gap.WORKSPACE = ORIGINAL_WORKSPACE
    14521478    """
    1453     if os.path.exists(WORKSPACE):
    1454         os.unlink(WORKSPACE)
    1455 
    14561479    # Delete all gap workspaces that haven't been used in the last
    14571480    # week, to avoid needless cruft.  I had an install on sage.math
    14581481    # with 90 of these, since I run a lot of different versions of
  • sage/interfaces/interface.py

    diff --git a/sage/interfaces/interface.py b/sage/interfaces/interface.py
    a b  
    516516            return ParentWithBase.__getattribute__(self, attrname)
    517517        except AttributeError:
    518518            if attrname[:1] == "_":
    519                 raise AttributeError
     519                raise
    520520            return self._function_class()(self, attrname)
    521521
    522522    def __cmp__(self, other):