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 ...@@ -50,6 +50,11 @@ Unreleased
``FileObjectPosix``. This unifies the code with the Python 3 ``FileObjectPosix``. This unifies the code with the Python 3
implementation, and fixes problems with using ``seek()``. See implementation, and fixes problems with using ``seek()``. See
:issue:`151`. :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) 1.1a2 (Jul 8, 2015)
=================== ===================
......
...@@ -280,8 +280,18 @@ def patch_subprocess(): ...@@ -280,8 +280,18 @@ def patch_subprocess():
patch_module('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, 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).""" """Do all of the default monkey patching (calls every other applicable function in this module)."""
# order is important # order is important
if os: if os:
...@@ -304,6 +314,8 @@ def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=Tru ...@@ -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') raise ValueError('gevent.httplib is no longer provided, httplib must be False')
if subprocess: if subprocess:
patch_subprocess() patch_subprocess()
if builtins:
patch_builtins()
if __name__ == '__main__': 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