Commit f307ee4c authored by Jason Madden's avatar Jason Madden

Add a monkey-patch for __import__ that properly locks multiple greenlets....

Add a monkey-patch for __import__ that properly locks multiple greenlets. Apply it automatically under python 2 (not needed on Py3). Fixes #108.
parent 3fc15b10
......@@ -50,6 +50,11 @@ Unreleased
``FileObjectPosix``. This unifies the code with the Python 3
implementation, and fixes problems with using ``seek()``. See
:issue:`151`.
- Under Python 2, importing a module that uses gevent blocking
functions at its top level from multiple greenlets no longer
produces import errors (Python 3 handles this case natively).
Reported in :issue:`108` by shaun and initial fix based on code by
Sylvain Zimmer.
1.1a2 (Jul 8, 2015)
===================
......
......@@ -280,8 +280,18 @@ def patch_subprocess():
patch_module('subprocess')
def patch_builtins():
"""Make the builtin __import__ function greenlet safe under Python 2"""
# https://github.com/gevent/gevent/issues/108
# Note that this is only needed in Python 2; under Python 3 (at least the versions
# we support) import locks are not global, they're per-module.
if sys.version_info[:2] < (3, 3):
patch_module('builtins')
def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, httplib=False,
subprocess=True, sys=False, aggressive=True, Event=False):
subprocess=True, sys=False, aggressive=True, Event=False,
builtins=True):
"""Do all of the default monkey patching (calls every other applicable function in this module)."""
# order is important
if os:
......@@ -304,6 +314,8 @@ def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=Tru
raise ValueError('gevent.httplib is no longer provided, httplib must be False')
if subprocess:
patch_subprocess()
if builtins:
patch_builtins()
if __name__ == '__main__':
......
from gevent import sleep
sleep(0.01)
x = "done"
#!/usr/bin/python
# See https://github.com/gevent/gevent/issues/108
import gevent
from gevent import monkey
monkey.patch_all()
import_errors = []
def some_func():
try:
from _blocks_at_top_level import x
assert x == 'done'
except ImportError as e:
import_errors.append(e)
gs = [gevent.spawn(some_func) for i in range(2)]
gevent.joinall(gs)
assert not import_errors, import_errors
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment