Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/multiprocessing/__init__.py

    r2 r391  
    1010#
    1111# Try calling `multiprocessing.doc.main()` to read the html
    12 # documentation in in a webbrowser.
     12# documentation in a webbrowser.
    1313#
    1414#
     
    3939# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    4040# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     41# SUCH DAMAGE.
    4142#
    4243
     
    116117            num = 0
    117118    elif 'bsd' in sys.platform or sys.platform == 'darwin':
     119        comm = '/sbin/sysctl -n hw.ncpu'
     120        if sys.platform == 'darwin':
     121            comm = '/usr' + comm
    118122        try:
    119             num = int(os.popen('sysctl -n hw.ncpu').read())
     123            with os.popen(comm) as p:
     124                num = int(p.read())
    120125        except ValueError:
    121126            num = 0
     
    220225    return JoinableQueue(maxsize)
    221226
    222 def Pool(processes=None, initializer=None, initargs=()):
     227def Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None):
    223228    '''
    224229    Returns a process pool object
    225230    '''
    226231    from multiprocessing.pool import Pool
    227     return Pool(processes, initializer, initargs)
     232    return Pool(processes, initializer, initargs, maxtasksperchild)
    228233
    229234def RawValue(typecode_or_type, *args):
  • python/trunk/Lib/multiprocessing/connection.py

    r2 r391  
    44# multiprocessing/connection.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    161187        if duplex:
    162188            s1, s2 = socket.socketpair()
     189            s1.setblocking(True)
     190            s2.setblocking(True)
    163191            c1 = _multiprocessing.Connection(os.dup(s1.fileno()))
    164192            c2 = _multiprocessing.Connection(os.dup(s2.fileno()))
     
    173201
    174202else:
    175 
    176     from ._multiprocessing import win32
     203    from _multiprocessing import win32
    177204
    178205    def Pipe(duplex=True):
     
    224251    def __init__(self, address, family, backlog=1):
    225252        self._socket = socket.socket(getattr(socket, family))
    226         self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    227         self._socket.bind(address)
    228         self._socket.listen(backlog)
    229         self._address = self._socket.getsockname()
     253        try:
     254            self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
     255            self._socket.setblocking(True)
     256            self._socket.bind(address)
     257            self._socket.listen(backlog)
     258            self._address = self._socket.getsockname()
     259        except socket.error:
     260            self._socket.close()
     261            raise
    230262        self._family = family
    231263        self._last_accepted = None
     
    239271
    240272    def accept(self):
    241         s, self._last_accepted = self._socket.accept()
     273        while True:
     274            try:
     275                s, self._last_accepted = self._socket.accept()
     276            except socket.error as e:
     277                if e.args[0] != errno.EINTR:
     278                    raise
     279            else:
     280                break
     281        s.setblocking(True)
    242282        fd = duplicate(s.fileno())
    243283        conn = _multiprocessing.Connection(fd)
     
    255295    Return a connection object connected to the socket given by `address`
    256296    '''
    257     family = address_type(address)
    258     s = socket.socket( getattr(socket, family) )
     297    family = getattr(socket, address_type(address))
    259298    t = _init_timeout()
    260299
    261300    while 1:
     301        s = socket.socket(family)
     302        s.setblocking(True)
    262303        try:
    263304            s.connect(address)
    264305        except socket.error, e:
     306            s.close()
    265307            if e.args[0] != errno.ECONNREFUSED or _check_timeout(t):
    266308                debug('failed to connect to address %s', address)
     
    319361                win32.ConnectNamedPipe(handle, win32.NULL)
    320362            except WindowsError, e:
    321                 if e.args[0] != win32.ERROR_PIPE_CONNECTED:
     363                # ERROR_NO_DATA can occur if a client has already connected,
     364                # written data and then disconnected -- see Issue 14725.
     365                if e.args[0] not in (win32.ERROR_PIPE_CONNECTED,
     366                                     win32.ERROR_NO_DATA):
    322367                    raise
    323368            return _multiprocessing.PipeConnection(handle)
  • python/trunk/Lib/multiprocessing/dummy/__init__.py

    r2 r391  
    44# multiprocessing/dummy/__init__.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    4571        assert self._parent is current_process()
    4672        self._start_called = True
    47         self._parent._children[self] = None
     73        if hasattr(self._parent, '_children'):
     74            self._parent._children[self] = None
    4875        threading.Thread.start(self)
    4976
  • python/trunk/Lib/multiprocessing/dummy/connection.py

    r2 r391  
    44# multiprocessing/dummy/connection.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
  • python/trunk/Lib/multiprocessing/forking.py

    r2 r391  
    44# multiprocessing/forking.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    1036import sys
    1137import signal
     38import errno
    1239
    1340from multiprocessing import util, process
     
    104131        def poll(self, flag=os.WNOHANG):
    105132            if self.returncode is None:
    106                 pid, sts = os.waitpid(self.pid, flag)
     133                while True:
     134                    try:
     135                        pid, sts = os.waitpid(self.pid, flag)
     136                    except os.error as e:
     137                        if e.errno == errno.EINTR:
     138                            continue
     139                        # Child process not yet created. See #1731717
     140                        # e.errno == errno.ECHILD == 10
     141                        return None
     142                    else:
     143                        break
    107144                if pid == self.pid:
    108145                    if os.WIFSIGNALED(sts):
     
    151188    import time
    152189
    153     from ._multiprocessing import win32, Connection, PipeConnection
     190    from _multiprocessing import win32, Connection, PipeConnection
    154191    from .util import Finalize
    155192
     
    168205    TERMINATE = 0x10000
    169206    WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
     207    WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
    170208
    171209    exit = win32.ExitProcess
     
    177215    #
    178216
    179     if sys.executable.lower().endswith('pythonservice.exe'):
     217    if WINSERVICE:
    180218        _python_exe = os.path.join(sys.exec_prefix, 'python.exe')
    181219    else:
     
    305343        Returns prefix of command line used for spawning a child process
    306344        '''
    307         if process.current_process()._identity==() and is_forking(sys.argv):
     345        if getattr(process.current_process(), '_inheriting', False):
    308346            raise RuntimeError('''
    309347            Attempt to start a new process before the current process
     
    324362        else:
    325363            prog = 'from multiprocessing.forking import main; main()'
    326             return [_python_exe, '-c', prog, '--multiprocessing-fork']
     364            opts = util._args_from_interpreter_flags()
     365            return [_python_exe] + opts + ['-c', prog, '--multiprocessing-fork']
    327366
    328367
    329368    def main():
    330369        '''
    331         Run code specifed by data received over pipe
     370        Run code specified by data received over pipe
    332371        '''
    333372        assert is_forking(sys.argv)
     
    367406            d['log_level'] = _logger.getEffectiveLevel()
    368407
    369         if not WINEXE:
     408        if not WINEXE and not WINSERVICE:
    370409            main_path = getattr(sys.modules['__main__'], '__file__', None)
    371410            if not main_path and sys.argv[0] not in ('', '-c'):
  • python/trunk/Lib/multiprocessing/heap.py

    r2 r391  
    44# multiprocessing/heap.py
    55#
    6 # Copyright (c) 2007-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    2753if sys.platform == 'win32':
    2854
    29     from ._multiprocessing import win32
     55    from _multiprocessing import win32
    3056
    3157    class Arena(object):
     
    76102        self._allocated_blocks = set()
    77103        self._arenas = []
     104        # list of pending blocks to free - see free() comment below
     105        self._pending_free_blocks = []
    78106
    79107    @staticmethod
     
    150178        return start, stop
    151179
     180    def _free_pending_blocks(self):
     181        # Free all the blocks in the pending list - called with the lock held.
     182        while True:
     183            try:
     184                block = self._pending_free_blocks.pop()
     185            except IndexError:
     186                break
     187            self._allocated_blocks.remove(block)
     188            self._free(block)
     189
    152190    def free(self, block):
    153191        # free a block returned by malloc()
     192        # Since free() can be called asynchronously by the GC, it could happen
     193        # that it's called while self._lock is held: in that case,
     194        # self._lock.acquire() would deadlock (issue #12352). To avoid that, a
     195        # trylock is used instead, and if the lock can't be acquired
     196        # immediately, the block is added to a list of blocks to be freed
     197        # synchronously sometimes later from malloc() or free(), by calling
     198        # _free_pending_blocks() (appending and retrieving from a list is not
     199        # strictly thread-safe but under cPython it's atomic thanks to the GIL).
    154200        assert os.getpid() == self._lastpid
    155         self._lock.acquire()
    156         try:
    157             self._allocated_blocks.remove(block)
    158             self._free(block)
    159         finally:
    160             self._lock.release()
     201        if not self._lock.acquire(False):
     202            # can't acquire the lock right now, add the block to the list of
     203            # pending blocks to free
     204            self._pending_free_blocks.append(block)
     205        else:
     206            # we hold the lock
     207            try:
     208                self._free_pending_blocks()
     209                self._allocated_blocks.remove(block)
     210                self._free(block)
     211            finally:
     212                self._lock.release()
    161213
    162214    def malloc(self, size):
     
    166218            self.__init__()                     # reinitialize after fork
    167219        self._lock.acquire()
     220        self._free_pending_blocks()
    168221        try:
    169222            size = self._roundup(max(size,1), self._alignment)
  • python/trunk/Lib/multiprocessing/managers.py

    r2 r391  
    55# multiprocessing/managers.py
    66#
    7 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     7# Copyright (c) 2006-2008, R Oudkerk
     8# All rights reserved.
     9#
     10# Redistribution and use in source and binary forms, with or without
     11# modification, are permitted provided that the following conditions
     12# are met:
     13#
     14# 1. Redistributions of source code must retain the above copyright
     15#    notice, this list of conditions and the following disclaimer.
     16# 2. Redistributions in binary form must reproduce the above copyright
     17#    notice, this list of conditions and the following disclaimer in the
     18#    documentation and/or other materials provided with the distribution.
     19# 3. Neither the name of author nor the names of any contributors may be
     20#    used to endorse or promote products derived from this software
     21#    without specific prior written permission.
     22#
     23# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     24# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     27# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33# SUCH DAMAGE.
    834#
    935
     
    134160
    135161        # do authentication later
    136         self.listener = Listener(address=address, backlog=5)
     162        self.listener = Listener(address=address, backlog=16)
    137163        self.address = self.listener.address
    138164
    139         self.id_to_obj = {0: (None, ())}
     165        self.id_to_obj = {'0': (None, ())}
    140166        self.id_to_refcount = {}
    141167        self.mutex = threading.RLock()
     
    299325            keys.sort()
    300326            for ident in keys:
    301                 if ident != 0:
     327                if ident != '0':
    302328                    result.append('  %s:       refcount=%s\n    %s' %
    303329                                  (ident, self.id_to_refcount[ident],
     
    311337        Number of shared objects
    312338        '''
    313         return len(self.id_to_obj) - 1      # don't count ident=0
     339        return len(self.id_to_obj) - 1      # don't count ident='0'
    314340
    315341    def shutdown(self, c):
     
    476502        self._state.value = State.STARTED
    477503
    478     def start(self):
     504    def start(self, initializer=None, initargs=()):
    479505        '''
    480506        Spawn a server process for this manager object
    481507        '''
    482508        assert self._state.value == State.INITIAL
     509
     510        if initializer is not None and not hasattr(initializer, '__call__'):
     511            raise TypeError('initializer must be a callable')
    483512
    484513        # pipe over which we will retrieve address of server
     
    489518            target=type(self)._run_server,
    490519            args=(self._registry, self._address, self._authkey,
    491                   self._serializer, writer),
     520                  self._serializer, writer, initializer, initargs),
    492521            )
    493522        ident = ':'.join(str(i) for i in self._process._identity)
     
    510539
    511540    @classmethod
    512     def _run_server(cls, registry, address, authkey, serializer, writer):
     541    def _run_server(cls, registry, address, authkey, serializer, writer,
     542                    initializer=None, initargs=()):
    513543        '''
    514544        Create a server, report its address and run it
    515545        '''
     546        if initializer is not None:
     547            initializer(*initargs)
     548
    516549        # create server
    517550        server = cls._Server(registry, address, authkey, serializer)
     
    731764            exposed, token = result
    732765            proxytype = self._manager._registry[token.typeid][-1]
     766            token.address = self._token.address
    733767            proxy = proxytype(
    734768                token, self._serializer, manager=self._manager,
  • python/trunk/Lib/multiprocessing/pool.py

    r2 r391  
    44# multiprocessing/pool.py
    55#
    6 # Copyright (c) 2007-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    4369#
    4470
    45 def worker(inqueue, outqueue, initializer=None, initargs=()):
     71class MaybeEncodingError(Exception):
     72    """Wraps possible unpickleable errors, so they can be
     73    safely sent through the socket."""
     74
     75    def __init__(self, exc, value):
     76        self.exc = repr(exc)
     77        self.value = repr(value)
     78        super(MaybeEncodingError, self).__init__(self.exc, self.value)
     79
     80    def __str__(self):
     81        return "Error sending result: '%s'. Reason: '%s'" % (self.value,
     82                                                             self.exc)
     83
     84    def __repr__(self):
     85        return "<MaybeEncodingError: %s>" % str(self)
     86
     87
     88def worker(inqueue, outqueue, initializer=None, initargs=(), maxtasks=None):
     89    assert maxtasks is None or (type(maxtasks) == int and maxtasks > 0)
    4690    put = outqueue.put
    4791    get = inqueue.get
     
    5397        initializer(*initargs)
    5498
    55     while 1:
     99    completed = 0
     100    while maxtasks is None or (maxtasks and completed < maxtasks):
    56101        try:
    57102            task = get()
     
    69114        except Exception, e:
    70115            result = (False, e)
    71         put((job, i, result))
     116        try:
     117            put((job, i, result))
     118        except Exception as e:
     119            wrapped = MaybeEncodingError(e, result[1])
     120            debug("Possible encoding error while sending result: %s" % (
     121                wrapped))
     122            put((job, i, (False, wrapped)))
     123        completed += 1
     124    debug('worker exiting after %d tasks' % completed)
    72125
    73126#
     
    81134    Process = Process
    82135
    83     def __init__(self, processes=None, initializer=None, initargs=()):
     136    def __init__(self, processes=None, initializer=None, initargs=(),
     137                 maxtasksperchild=None):
    84138        self._setup_queues()
    85139        self._taskqueue = Queue.Queue()
    86140        self._cache = {}
    87141        self._state = RUN
     142        self._maxtasksperchild = maxtasksperchild
     143        self._initializer = initializer
     144        self._initargs = initargs
    88145
    89146        if processes is None:
     
    92149            except NotImplementedError:
    93150                processes = 1
    94 
     151        if processes < 1:
     152            raise ValueError("Number of processes must be at least 1")
     153
     154        if initializer is not None and not hasattr(initializer, '__call__'):
     155            raise TypeError('initializer must be a callable')
     156
     157        self._processes = processes
    95158        self._pool = []
    96         for i in range(processes):
    97             w = self.Process(
    98                 target=worker,
    99                 args=(self._inqueue, self._outqueue, initializer, initargs)
    100                 )
    101             self._pool.append(w)
    102             w.name = w.name.replace('Process', 'PoolWorker')
    103             w.daemon = True
    104             w.start()
     159        self._repopulate_pool()
     160
     161        self._worker_handler = threading.Thread(
     162            target=Pool._handle_workers,
     163            args=(self, )
     164            )
     165        self._worker_handler.daemon = True
     166        self._worker_handler._state = RUN
     167        self._worker_handler.start()
     168
    105169
    106170        self._task_handler = threading.Thread(
     
    123187            self, self._terminate_pool,
    124188            args=(self._taskqueue, self._inqueue, self._outqueue, self._pool,
    125                   self._task_handler, self._result_handler, self._cache),
     189                  self._worker_handler, self._task_handler,
     190                  self._result_handler, self._cache),
    126191            exitpriority=15
    127192            )
     193
     194    def _join_exited_workers(self):
     195        """Cleanup after any worker processes which have exited due to reaching
     196        their specified lifetime.  Returns True if any workers were cleaned up.
     197        """
     198        cleaned = False
     199        for i in reversed(range(len(self._pool))):
     200            worker = self._pool[i]
     201            if worker.exitcode is not None:
     202                # worker exited
     203                debug('cleaning up worker %d' % i)
     204                worker.join()
     205                cleaned = True
     206                del self._pool[i]
     207        return cleaned
     208
     209    def _repopulate_pool(self):
     210        """Bring the number of pool processes up to the specified number,
     211        for use after reaping workers which have exited.
     212        """
     213        for i in range(self._processes - len(self._pool)):
     214            w = self.Process(target=worker,
     215                             args=(self._inqueue, self._outqueue,
     216                                   self._initializer,
     217                                   self._initargs, self._maxtasksperchild)
     218                            )
     219            self._pool.append(w)
     220            w.name = w.name.replace('Process', 'PoolWorker')
     221            w.daemon = True
     222            w.start()
     223            debug('added worker')
     224
     225    def _maintain_pool(self):
     226        """Clean up any exited workers and start replacements for them.
     227        """
     228        if self._join_exited_workers():
     229            self._repopulate_pool()
    128230
    129231    def _setup_queues(self):
     
    205307            if extra:
    206308                chunksize += 1
     309        if len(iterable) == 0:
     310            chunksize = 0
    207311
    208312        task_batches = Pool._get_tasks(func, iterable, chunksize)
     
    211315                              for i, x in enumerate(task_batches)), None))
    212316        return result
     317
     318    @staticmethod
     319    def _handle_workers(pool):
     320        thread = threading.current_thread()
     321
     322        # Keep maintaining workers until the cache gets drained, unless the pool
     323        # is terminated.
     324        while thread._state == RUN or (pool._cache and thread._state != TERMINATE):
     325            pool._maintain_pool()
     326            time.sleep(0.1)
     327        # send sentinel to stop workers
     328        pool._taskqueue.put(None)
     329        debug('worker handler exiting')
    213330
    214331    @staticmethod
     
    327444        if self._state == RUN:
    328445            self._state = CLOSE
    329             self._taskqueue.put(None)
     446            self._worker_handler._state = CLOSE
    330447
    331448    def terminate(self):
    332449        debug('terminating pool')
    333450        self._state = TERMINATE
     451        self._worker_handler._state = TERMINATE
    334452        self._terminate()
    335453
     
    337455        debug('joining pool')
    338456        assert self._state in (CLOSE, TERMINATE)
     457        self._worker_handler.join()
    339458        self._task_handler.join()
    340459        self._result_handler.join()
     
    353472    @classmethod
    354473    def _terminate_pool(cls, taskqueue, inqueue, outqueue, pool,
    355                         task_handler, result_handler, cache):
     474                        worker_handler, task_handler, result_handler, cache):
    356475        # this is guaranteed to only be called once
    357476        debug('finalizing pool')
    358477
     478        worker_handler._state = TERMINATE
    359479        task_handler._state = TERMINATE
    360         taskqueue.put(None)                 # sentinel
    361480
    362481        debug('helping task handler/workers to finish')
     
    368487        outqueue.put(None)                  # sentinel
    369488
     489        # We must wait for the worker handler to exit before terminating
     490        # workers because we don't want workers to be restarted behind our back.
     491        debug('joining worker handler')
     492        if threading.current_thread() is not worker_handler:
     493            worker_handler.join(1e100)
     494
     495        # Terminate workers which haven't already finished.
    370496        if pool and hasattr(pool[0], 'terminate'):
    371497            debug('terminating workers')
    372498            for p in pool:
    373                 p.terminate()
     499                if p.exitcode is None:
     500                    p.terminate()
    374501
    375502        debug('joining task handler')
    376         task_handler.join(1e100)
     503        if threading.current_thread() is not task_handler:
     504            task_handler.join(1e100)
    377505
    378506        debug('joining result handler')
    379         result_handler.join(1e100)
     507        if threading.current_thread() is not result_handler:
     508            result_handler.join(1e100)
    380509
    381510        if pool and hasattr(pool[0], 'terminate'):
    382511            debug('joining pool workers')
    383512            for p in pool:
    384                 p.join()
     513                if p.is_alive():
     514                    # worker has not yet exited
     515                    debug('cleaning up worker %d' % p.pid)
     516                    p.join()
    385517
    386518#
     
    434566        del self._cache[self._job]
    435567
     568AsyncResult = ApplyResult       # create alias -- see #17805
     569
    436570#
    437571# Class whose instances are returned by `Pool.map_async()`
     
    448582            self._number_left = 0
    449583            self._ready = True
     584            del cache[self._job]
    450585        else:
    451586            self._number_left = length//chunksize + bool(length % chunksize)
  • python/trunk/Lib/multiprocessing/process.py

    r2 r391  
    44# multiprocessing/process.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    180206    def ident(self):
    181207        '''
    182         Return indentifier (PID) of process or `None` if it has yet to start
     208        Return identifier (PID) of process or `None` if it has yet to start
    183209        '''
    184210        if self is _current_process:
     
    237263            if not e.args:
    238264                exitcode = 1
    239             elif type(e.args[0]) is int:
     265            elif isinstance(e.args[0], int):
    240266                exitcode = e.args[0]
    241267            else:
    242                 sys.stderr.write(e.args[0] + '\n')
     268                sys.stderr.write(str(e.args[0]) + '\n')
    243269                sys.stderr.flush()
    244                 exitcode = 1
     270                exitcode = 0 if isinstance(e.args[0], str) else 1
    245271        except:
    246272            exitcode = 1
  • python/trunk/Lib/multiprocessing/queues.py

    r2 r391  
    44# multiprocessing/queues.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    101127                raise Empty
    102128            try:
    103                 if not self._poll(block and (deadline-time.time()) or 0.0):
     129                if block:
     130                    timeout = deadline - time.time()
     131                    if timeout < 0 or not self._poll(timeout):
     132                        raise Empty
     133                elif not self._poll():
    104134                    raise Empty
    105135                res = self._recv()
     
    163193
    164194        # On process exit we will wait for data to be flushed to pipe.
    165         #
    166         # However, if this process created the queue then all
    167         # processes which use the queue will be descendants of this
    168         # process.  Therefore waiting for the queue to be flushed
    169         # is pointless once all the child processes have been joined.
    170         created_by_this_process = (self._opid == os.getpid())
    171         if not self._joincancelled and not created_by_this_process:
     195        if not self._joincancelled:
    172196            self._jointhread = Finalize(
    173197                self._thread, Queue._finalize_join,
  • python/trunk/Lib/multiprocessing/reduction.py

    r2 r391  
    55# multiprocessing/reduction.py
    66#
    7 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     7# Copyright (c) 2006-2008, R Oudkerk
     8# All rights reserved.
     9#
     10# Redistribution and use in source and binary forms, with or without
     11# modification, are permitted provided that the following conditions
     12# are met:
     13#
     14# 1. Redistributions of source code must retain the above copyright
     15#    notice, this list of conditions and the following disclaimer.
     16# 2. Redistributions in binary form must reproduce the above copyright
     17#    notice, this list of conditions and the following disclaimer in the
     18#    documentation and/or other materials provided with the distribution.
     19# 3. Neither the name of author nor the names of any contributors may be
     20#    used to endorse or promote products derived from this software
     21#    without specific prior written permission.
     22#
     23# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     24# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     27# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33# SUCH DAMAGE.
    834#
    935
     
    3561if sys.platform == 'win32':
    3662    import _subprocess
    37     from ._multiprocessing import win32
     63    from _multiprocessing import win32
    3864
    3965    def send_handle(conn, handle, destination_pid):
  • python/trunk/Lib/multiprocessing/sharedctypes.py

    r2 r391  
    44# multiprocessing/sharedctypes.py
    55#
    6 # Copyright (c) 2007-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    5379    '''
    5480    type_ = typecode_to_type.get(typecode_or_type, typecode_or_type)
    55     if isinstance(size_or_initializer, int):
     81    if isinstance(size_or_initializer, (int, long)):
    5682        type_ = type_ * size_or_initializer
    57         return _new_value(type_)
     83        obj = _new_value(type_)
     84        ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj))
     85        return obj
    5886    else:
    5987        type_ = type_ * len(size_or_initializer)
  • python/trunk/Lib/multiprocessing/synchronize.py

    r2 r391  
    44# multiprocessing/synchronize.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    5985        self.acquire = self._semlock.acquire
    6086        self.release = self._semlock.release
    61         self.__enter__ = self._semlock.__enter__
    62         self.__exit__ = self._semlock.__exit__
     87
     88    def __enter__(self):
     89        return self._semlock.__enter__()
     90
     91    def __exit__(self, *args):
     92        return self._semlock.__exit__(*args)
    6393
    6494    def __getstate__(self):
     
    182212        self._make_methods()
    183213
     214    def __enter__(self):
     215        return self._lock.__enter__()
     216
     217    def __exit__(self, *args):
     218        return self._lock.__exit__(*args)
     219
    184220    def _make_methods(self):
    185221        self.acquire = self._lock.acquire
    186222        self.release = self._lock.release
    187         self.__enter__ = self._lock.__enter__
    188         self.__exit__ = self._lock.__exit__
    189223
    190224    def __repr__(self):
     
    193227                           self._woken_count._semlock._get_value())
    194228        except Exception:
    195             num_waiters = 'unkown'
     229            num_waiters = 'unknown'
    196230        return '<Condition(%s, %s)>' % (self._lock, num_waiters)
    197231
     
    302336            else:
    303337                self._cond.wait(timeout)
     338
     339            if self._flag.acquire(False):
     340                self._flag.release()
     341                return True
     342            return False
    304343        finally:
    305344            self._cond.release()
  • python/trunk/Lib/multiprocessing/util.py

    r2 r391  
    44# multiprocessing/util.py
    55#
    6 # Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    1238import threading        # we want threading to install it's
    1339                        # cleanup function before multiprocessing does
     40from subprocess import _args_from_interpreter_flags
    1441
    1542from multiprocessing.process import current_process, active_children
     
    222249    the same priority will be called in reverse order of creation.
    223250    '''
     251    if _finalizer_registry is None:
     252        # This function may be called after this module's globals are
     253        # destroyed.  See the _exit_function function in this module for more
     254        # notes.
     255        return
     256
    224257    if minpriority is None:
    225258        f = lambda p : p[0][0] is not None
     
    253286_exiting = False
    254287
    255 def _exit_function():
     288def _exit_function(info=info, debug=debug, _run_finalizers=_run_finalizers,
     289                   active_children=active_children,
     290                   current_process=current_process):
     291    # NB: we hold on to references to functions in the arglist due to the
     292    # situation described below, where this function is called after this
     293    # module's globals are destroyed.
     294
    256295    global _exiting
    257296
     
    260299    _run_finalizers(0)
    261300
    262     for p in active_children():
    263         if p._daemonic:
    264             info('calling terminate() for daemon %s', p.name)
    265             p._popen.terminate()
    266 
    267     for p in active_children():
    268         info('calling join() for process %s', p.name)
    269         p.join()
     301    if current_process() is not None:
     302        # NB: we check if the current process is None here because if
     303        # it's None, any call to ``active_children()`` will throw an
     304        # AttributeError (active_children winds up trying to get
     305        # attributes from util._current_process).  This happens in a
     306        # variety of shutdown circumstances that are not well-understood
     307        # because module-scope variables are not apparently supposed to
     308        # be destroyed until after this function is called.  However,
     309        # they are indeed destroyed before this function is called.  See
     310        # issues 9775 and 15881.  Also related: 4106, 9205, and 9207.
     311
     312        for p in active_children():
     313            if p._daemonic:
     314                info('calling terminate() for daemon %s', p.name)
     315                p._popen.terminate()
     316
     317        for p in active_children():
     318            info('calling join() for process %s', p.name)
     319            p.join()
    270320
    271321    debug('running the remaining "atexit" finalizers')
     
    280330class ForkAwareThreadLock(object):
    281331    def __init__(self):
     332        self._reset()
     333        register_after_fork(self, ForkAwareThreadLock._reset)
     334
     335    def _reset(self):
    282336        self._lock = threading.Lock()
    283337        self.acquire = self._lock.acquire
    284338        self.release = self._lock.release
    285         register_after_fork(self, ForkAwareThreadLock.__init__)
    286339
    287340class ForkAwareLocal(threading.local):
Note: See TracChangeset for help on using the changeset viewer.