#! python # -*- coding: utf-8 -*- """Module to patch python 2.5 multiprocessing module. """ import sys import multiprocessing import multiprocessing.managers import multiprocessing.connection __all__ = ('patch_all', ) def _patched_issue6056_SocketClient(address, family=None, authkey=None): """Patched version for multiprocessing.connections.SocketClient to workaround issue 6056. This is a copy of built-in implementation except the socket.setblocking(). """ import socket, time, errno from multiprocessing.connection import address_type, _multiprocessing,\ duplicate, debug family = address_type(address) s = socket.socket( getattr(socket, family) ) # FIX: Set the socket to blocking s.setblocking(1) while 1: try: s.connect(address) except socket.error, e: if e.args[0] != errno.ECONNREFUSED: # connection refused debug('failed to connect to address %s', address) raise time.sleep(0.01) else: break else: raise fd = duplicate(s.fileno()) conn = _multiprocessing.Connection(fd) s.close() return conn def _patch_multiprocessing_manager_issue6056(): """Due to some implementation issue in multiprocessing.managers.BaseManager, the socket-based manager may be broken by socket.setdefaulttimeout(). Refer to http://bugs.python.org/issue6056 This patch replaces multiprocessing.managers' default Client creator for serializer type 'pickle' with a patched version (_patched_issue6056_client). """ multiprocessing.connection.SocketClient = \ _patched_issue6056_SocketClient #-------------------------------------------------------------------------------- def _patch_multiprocessing_log_issue18(): """Patch to fix multiprocessing.log issue. http://code.google.com/p/python-multiprocessing/issues/detail?id=18 Make sure process name is recorded when loggers are used. As we will avoid patching multiprocessing directly, we will use this patch method. """ from multiprocessing.process import current_process import logging logging._acquireLock() try: OldLoggerClass = logging.getLoggerClass() if not getattr(OldLoggerClass, '_process_aware', False): class ProcessAwareLogger(OldLoggerClass): _process_aware = True def makeRecord(self, *args, **kwds): record = OldLoggerClass.makeRecord(self, *args, **kwds) record.processName = current_process()._name return record logging.setLoggerClass(ProcessAwareLogger) finally: logging._releaseLock() #--------------------------------------------------------------------------- def _add_logging_sublevels(): """Register multiprocessing level names to logging module, so logging config file will work. """ import logging logging.addLevelName(multiprocessing.SUBDEBUG, 'SUBDEBUG') logging.addLevelName(multiprocessing.SUBWARNING, 'SUBWARNING') def patch_all(): if (2, 5) <= sys.version_info < (2, 6) and \ multiprocessing.__version__ == '2.6.2.1': _patch_multiprocessing_manager_issue6056() _patch_multiprocessing_log_issue18() _add_logging_sublevels()