Ticket #9616: trac_9616-backout_only_some_of_9501.patch

File trac_9616-backout_only_some_of_9501.patch, 4.8 KB (added by leif, 11 years ago)

Backouts only ticket-relevant parts of #9501 (subset of Mitesh's patch)

  • sage/parallel/all.py

    # HG changeset patch
    # User Leif Leonhardy <not.really@online.de>
    # Date 1280360387 -7200
    # Node ID 134931525f957d2e27f95f70141aa557292df9f9
    # Parent  c7fa490f5782fa190af65bfbedcae934bd525ca2
    #9616: Backout/revert parts of #9501 (@fork decorator b/c of NFS problems)
    
    diff -r c7fa490f5782 -r 134931525f95 sage/parallel/all.py
    a b  
    1 from decorate import parallel, fork
     1from decorate import parallel
    22
  • sage/parallel/decorate.py

    diff -r c7fa490f5782 -r 134931525f95 sage/parallel/decorate.py
    a b  
    186186        return Parallel()(p_iter)
    187187    return Parallel(p_iter, ncpus, **kwds)
    188188   
    189 
    190 
    191 ###################################################################
    192 # The @fork decorator -- run a function with no sideeffects in memory
    193 # (so only side effects are on disk).
    194 # We have both a function and a class below, so that the decorator
    195 # can be used with or without options:
    196 #   @fork
    197 #   def f(...): ...
    198 # and
    199 #   @fork(...options...):
    200 #   def f(...): ...
    201 ###################################################################
    202 
    203 class Fork:
    204     """
    205     A fork decorator class.
    206     """
    207     def __init__(self, timeout=0):
    208         """
    209         INPUT:
    210             - ``timeout`` -- (default: 0) kills subrocess after this many
    211               seconds, or if timeout=0, do not kill the subprocess.
    212 
    213         EXAMPLES::
    214        
    215             sage: sage.parallel.decorate.Fork()
    216             <sage.parallel.decorate.Fork instance at 0x...>
    217             sage: sage.parallel.decorate.Fork(timeout=3)
    218             <sage.parallel.decorate.Fork instance at 0x...>
    219 
    220         """
    221         self.timeout = timeout
    222        
    223     def __call__(self, f):
    224         """
    225         INPUT:
    226             - f -- a function
    227         OUTPUT:
    228             - a decorated function
    229 
    230         EXAMPLES::
    231        
    232             sage: F = sage.parallel.decorate.Fork(timeout=3)
    233             sage: def g(n,m): return n+m
    234             sage: h = F(g)     # indirect doctest
    235             sage: h(2,3)
    236             5           
    237         """
    238         P = Parallel(p_iter='fork', ncpus=1, timeout=self.timeout)
    239         g = P(f)
    240         def h(*args, **kwds):
    241             return list(g([(args, kwds)]))[0][1]
    242         return h
    243 
    244 def fork(f=None, timeout=0):
    245     """
    246     Decorate a function so that when called it runs in a forked
    247     subprocess.  This means that it won't have any in-memory
    248     side-effects on the master Sage process.  The pexpect interfaces
    249     are all reset.
    250    
    251     INPUT:
    252         - ``f`` -- a function
    253         - ``timeout`` -- (default: 0) kills subrocess after this many
    254           seconds, or if timeout=0, do not kill the subprocess.
    255 
    256     .. warning::
    257 
    258         The forked subprocesses will not have access to data created
    259         in pexpect interfaces.  This behavior with respect to pexpect
    260         interfaces is very important to keep in mind when setting up
    261         certain computations. It's the one big limitation of this
    262         decorator.
    263 
    264     EXAMPLES::
    265 
    266     We create a function and run it with the fork decorator.  Note that
    267     it does not have a side effect.  Despite trying to change that global
    268     variable "a" below, it does not get changed.::
    269    
    270         sage: a = 5
    271         sage: @fork
    272         ... def g(n, m):
    273         ...       global a
    274         ...       a = 10
    275         ...       return factorial(n).ndigits() + m
    276         sage: g(5, m=5)
    277         8
    278         sage: a
    279         5
    280 
    281     We use fork to make sure that the function dies after 1 second no matter what::
    282    
    283         sage: @fork(timeout=1)
    284         ... def g(n, m): return factorial(n).ndigits() + m
    285         sage: g(5, m=5)
    286         8
    287         sage: g(10^7, m=5)
    288         Killing subprocess ... with input ((10000000,), {'m': 5}) which took too long
    289         'NO DATA (timed out)'
    290 
    291     We illustrate that pexpect interface state is not effected by
    292     forked functions (they get their own new pexpect interfaces!)::
    293    
    294         sage: gp.eval('a = 5')
    295         '5'
    296         sage: @fork()
    297         ... def g():
    298         ...       gp.eval('a = 10')
    299         ...       return gp.eval('a')
    300         sage: g()
    301         '10'
    302         sage: gp.eval('a')
    303         '5'
    304 
    305     We illustrate that the forked function has its own pexpect interface.::
    306    
    307         sage: gp.eval('a = 15')
    308         '15'
    309         sage: @fork()
    310         ... def g(): return gp.eval('a')
    311         sage: g()
    312         'a'
    313 
    314     We illustrate that segfaulting subprocesses are no trouble at all::
    315 
    316         sage: cython('def f(): print <char*>0')
    317         sage: @fork
    318         ... def g(): f()
    319         sage: g()
    320         'NO DATA'
    321     """
    322     F = Fork(timeout=timeout)
    323     return F(f) if f else F