Ejemplo n.º 1
0
 def importer():
     imp.acquire_lock()
     sys.modules[fake_module_name] = partial_module
     import_started.set()
     time.sleep(0.01)  # Give the other thread time to try and acquire.
     sys.modules[fake_module_name] = complete_module
     imp.release_lock()
Ejemplo n.º 2
0
 def importer():
     imp.acquire_lock()
     sys.modules[fake_module_name] = partial_module
     import_started.set()
     time.sleep(0.01) # Give the other thread time to try and acquire.
     sys.modules[fake_module_name] = complete_module
     imp.release_lock()
Ejemplo n.º 3
0
 def importer():
     imp.acquire_lock()
     sys.modules[fake_module_name] = partial_module
     import_started.set()
     time.sleep(0.01)
     sys.modules[fake_module_name] = complete_module
     imp.release_lock()
Ejemplo n.º 4
0
def _get_module_lock(name):
    """Get or create the module lock for a given module name.

    Acquire/release internally the global import lock to protect
    _module_locks."""

    _imp.acquire_lock()
    try:
        try:
            lock = _module_locks[name]()
        except KeyError:
            lock = None

        if lock is None:
            if _thread is None:
                lock = _DummyModuleLock(name)
            else:
                lock = _ModuleLock(name)

            def cb(ref, name=name):
                _imp.acquire_lock()
                try:
                    # bpo-31070: Check if another thread created a new lock
                    # after the previous lock was destroyed
                    # but before the weakref callback was called.
                    if _module_locks.get(name) is ref:
                        del _module_locks[name]
                finally:
                    _imp.release_lock()

            _module_locks[name] = _weakref.ref(lock, cb)
    finally:
        _imp.release_lock()

    return lock
Ejemplo n.º 5
0
 def cb(ref, name=name):
     _imp.acquire_lock()
     try:
         # bpo-31070: Check if another thread created a new lock
         # after the previous lock was destroyed
         # but before the weakref callback was called.
         if _module_locks.get(name) is ref:
             del _module_locks[name]
     finally:
         _imp.release_lock()
Ejemplo n.º 6
0
 def restore(self):
     """Restores the modules that the saver knows about into
     sys.modules.
     """
     try:
         for modname, mod in six.iteritems(self._saved):
             if mod is not None:
                 sys.modules[modname] = mod
             else:
                 try:
                     del sys.modules[modname]
                 except KeyError:
                     pass
     finally:
         imp.release_lock()
Ejemplo n.º 7
0
 def fork_with_import_lock(level):
     release = 0
     in_child = False
     try:
         try:
             for i in range(level):
                 imp.acquire_lock()
                 release += 1
             pid = os.fork()
             in_child = not pid
         finally:
             for i in range(release):
                 imp.release_lock()
     except RuntimeError:
         if in_child:
             if verbose > 1:
                 print("RuntimeError in child")
             os._exit(1)
         raise
     if in_child:
         os._exit(0)
     self.wait_impl(pid)
Ejemplo n.º 8
0
 def fork_with_import_lock(level):
     release = 0
     in_child = False
     try:
         try:
             for i in range(level):
                 imp.acquire_lock()
                 release += 1
             pid = os.fork()
             in_child = not pid
         finally:
             for i in range(release):
                 imp.release_lock()
     except RuntimeError:
         if in_child:
             if verbose > 1:
                 print("RuntimeError in child")
             os._exit(1)
         raise
     if in_child:
         os._exit(0)
     self.wait_impl(pid)
Ejemplo n.º 9
0
def monkey_patch(**on):
    """Globally patches certain system modules to be greenthread-friendly.

    The keyword arguments afford some control over which modules are patched.
    If no keyword arguments are supplied, all possible modules are patched.
    If keywords are set to True, only the specified modules are patched.  E.g.,
    ``monkey_patch(socket=True, select=True)`` patches only the select and
    socket modules.  Most arguments patch the single module of the same name
    (os, time, select).  The exceptions are socket, which also patches the ssl
    module if present; and thread, which patches thread, threading, and Queue.

    It's safe to call monkey_patch multiple times.
    """

    # Workaround for import cycle observed as following in monotonic
    # RuntimeError: no suitable implementation for this system
    # see https://github.com/eventlet/eventlet/issues/401#issuecomment-325015989
    #
    # Make sure the hub is completely imported before any
    # monkey-patching, or we risk recursion if the process of importing
    # the hub calls into monkey-patched modules.
    eventlet.hubs.get_hub()

    accepted_args = set(('os', 'select', 'socket', 'thread', 'time', 'psycopg',
                         'MySQLdb', 'builtins', 'subprocess'))
    # To make sure only one of them is passed here
    assert not ('__builtin__' in on and 'builtins' in on)
    try:
        b = on.pop('__builtin__')
    except KeyError:
        pass
    else:
        on['builtins'] = b

    default_on = on.pop("all", None)

    for k in six.iterkeys(on):
        if k not in accepted_args:
            raise TypeError("monkey_patch() got an unexpected "
                            "keyword argument %r" % k)
    if default_on is None:
        default_on = not (True in on.values())
    for modname in accepted_args:
        if modname == 'MySQLdb':
            # MySQLdb is only on when explicitly patched for the moment
            on.setdefault(modname, False)
        if modname == 'builtins':
            on.setdefault(modname, False)
        on.setdefault(modname, default_on)

    if on['thread'] and not already_patched.get('thread'):
        _green_existing_locks()

    modules_to_patch = []
    for name, modules_function in [
        ('os', _green_os_modules),
        ('select', _green_select_modules),
        ('socket', _green_socket_modules),
        ('thread', _green_thread_modules),
        ('time', _green_time_modules),
        ('MySQLdb', _green_MySQLdb),
        ('builtins', _green_builtins),
        ('subprocess', _green_subprocess_modules),
    ]:
        if on[name] and not already_patched.get(name):
            modules_to_patch += modules_function()
            already_patched[name] = True

    if on['psycopg'] and not already_patched.get('psycopg'):
        try:
            from eventlet.support import psycopg2_patcher
            psycopg2_patcher.make_psycopg_green()
            already_patched['psycopg'] = True
        except ImportError:
            # note that if we get an importerror from trying to
            # monkeypatch psycopg, we will continually retry it
            # whenever monkey_patch is called; this should not be a
            # performance problem but it allows is_monkey_patched to
            # tell us whether or not we succeeded
            pass

    _threading = original('threading')
    imp.acquire_lock()
    try:
        for name, mod in modules_to_patch:
            orig_mod = sys.modules.get(name)
            if orig_mod is None:
                orig_mod = __import__(name)
            for attr_name in mod.__patched__:
                patched_attr = getattr(mod, attr_name, None)
                if patched_attr is not None:
                    setattr(orig_mod, attr_name, patched_attr)
            deleted = getattr(mod, '__deleted__', [])
            for attr_name in deleted:
                if hasattr(orig_mod, attr_name):
                    delattr(orig_mod, attr_name)

            # https://github.com/eventlet/eventlet/issues/592
            if name == 'threading' and register_at_fork:

                def fix_threading_active(
                    _global_dict=_threading.current_thread.__globals__,
                    # alias orig_mod as patched to reflect its new state
                    # https://github.com/eventlet/eventlet/pull/661#discussion_r509877481
                    _patched=orig_mod,
                ):
                    _prefork_active = [None]

                    def before_fork():
                        _prefork_active[0] = _global_dict['_active']
                        _global_dict['_active'] = _patched._active

                    def after_fork():
                        _global_dict['_active'] = _prefork_active[0]

                    register_at_fork(before=before_fork,
                                     after_in_parent=after_fork)

                fix_threading_active()
    finally:
        imp.release_lock()

    if sys.version_info >= (3, 3):
        import importlib._bootstrap
        thread = original('_thread')
        # importlib must use real thread locks, not eventlet.Semaphore
        importlib._bootstrap._thread = thread

        # Issue #185: Since Python 3.3, threading.RLock is implemented in C and
        # so call a C function to get the thread identifier, instead of calling
        # threading.get_ident(). Force the Python implementation of RLock which
        # calls threading.get_ident() and so is compatible with eventlet.
        import threading
        threading.RLock = threading._PyRLock

    # Issue #508: Since Python 3.7 queue.SimpleQueue is implemented in C,
    # causing a deadlock.  Replace the C implementation with the Python one.
    if sys.version_info >= (3, 7):
        import queue
        queue.SimpleQueue = queue._PySimpleQueue
Ejemplo n.º 10
0
 def __exit__(self, exc_type, exc_value, exc_traceback):
     """Release the import lock regardless of any raised exceptions."""
     _imp.release_lock()
Ejemplo n.º 11
0
 def release(self):
     _imp.release_lock()