eventlet / eventlet

Concurrent networking library for Python
https://eventlet.net
Other
1.24k stars 322 forks source link

SSL.py recursion crash in (eventlet > 0.17.4) and python 3.6 #371

Open Renmusxd opened 7 years ago

Renmusxd commented 7 years ago

Using python 3.6 with the following code causes an infinite recursion of python super calls leading to a crash

import eventlet
eventlet.monkey_patch()

import os
import socket
from flask import Flask, render_template, request, Response, send_file
from flask import make_response
from flask_socketio import SocketIO
from OpenSSL import SSL, crypto

'''
requirements.txt
cffi==1.9.1
click==6.6
cryptography==1.7.1
enum-compat==0.0.2
eventlet==0.20.1
Flask==0.12
Flask-SocketIO==2.8.2
greenlet==0.4.11
idna==2.2
itsdangerous==0.24
Jinja2==2.8.1
MarkupSafe==0.23
pyasn1==0.1.9
pycparser==2.17
pyOpenSSL==16.2.0
python-engineio==1.1.0
python-socketio==1.6.2
six==1.10.0
Werkzeug==0.11.15
'''

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
async_mode = None
socketio = SocketIO(app, async_mode=async_mode)
def create_self_signed_cert(certfile, keyfile, certargs, cert_dir="."):
    C_F = os.path.join(cert_dir, certfile)
    K_F = os.path.join(cert_dir, keyfile)
    if not os.path.exists(C_F) or not os.path.exists(K_F):
        k = crypto.PKey()
        k.generate_key(crypto.TYPE_RSA, 1024)
        cert = crypto.X509()
        cert.get_subject().C = certargs["Country"]
        cert.get_subject().ST = certargs["State"]
        cert.get_subject().L = certargs["City"]
        cert.get_subject().O = certargs["Organization"]
        cert.get_subject().OU = certargs["Org. Unit"]
        cert.get_subject().CN = 'Example'
        cert.set_serial_number(1000)
        cert.gmtime_adj_notBefore(0)
        cert.gmtime_adj_notAfter(315360000)
        cert.set_issuer(cert.get_subject())
        cert.set_pubkey(k)
        cert.sign(k, 'sha1')
        open(C_F, "wb").write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
        open(K_F, "wb").write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))

CERT_FILE = "cert.pem"
KEY_FILE = "key.pem"
create_self_signed_cert(CERT_FILE, KEY_FILE,
                            certargs=
                            {"Country": "US",
                             "State": "NY",
                             "City": "Ithaca",
                             "Organization": "Python-Bugs",
                             "Org. Unit": "Proof of Concept"})
socketio.run(app, debug=True, use_reloader=False, certfile=CERT_FILE, keyfile=KEY_FILE, port=5500)

Trace:

Traceback (most recent call last): File "[...]/server.py", line 231, in socketio.run(app, debug=True, use_reloader=False, certfile=CERT_FILE, keyfile=KEY_FILE, port=5500) File "[...]/.virtualenvs/bot/lib/python3.6/site-packages/flask_socketio/init.py", line 493, in run run_server() File "[...]/.virtualenvs/bot/lib/python3.6/site-packages/flask_socketio/init.py", line 485, in run_server ssl_params) File "[...]/.virtualenvs/bot/lib/python3.6/site-packages/eventlet/convenience.py", line 126, in wrap_ssl return wrap_ssl_impl(sock, *a, *kw) File "[...]/.virtualenvs/bot/lib/python3.6/site-packages/eventlet/green/ssl.py", line 379, in wrap_socket return GreenSSLSocket(sock, a, kw) File "[...]/.virtualenvs/bot/lib/python3.6/site-packages/eventlet/green/ssl.py", line 68, in init ca_certs, do_handshake_on_connect and six.PY2, *args, **kw) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 737, in init self._context.verify_mode = cert_reqs File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 479, in verify_mode super(SSLContext, SSLContext).verify_mode.set(self, value) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 479, in verify_mode super(SSLContext, SSLContext).verify_mode.set(self, value) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ssl.py", line 479, in verify_mode super(SSLContext, SSLContext).verify_mode.set(self, value) [Previous line repeated 325 more times] RecursionError: maximum recursion depth exceeded while calling a Python object

Issue also posted to http://bugs.python.org/issue29149, and https://github.com/miguelgrinberg/Flask-SocketIO/issues/193, but since it's eventlet version dependent may also be relevant here.

Renmusxd commented 7 years ago

Simpler code to reproduce bug:

#!/usr/bin/env python3

import eventlet
eventlet.monkey_patch()

import sys

from eventlet import wsgi

def hello_world (env, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['Hello, World!\r\n']

def main ():
    listener = eventlet.wrap_ssl(
        eventlet.listen(('127.0.0.1', 8000)),
        certfile='does-not-exist',
        keyfile='does-not-exist',
        server_side=True)

    wsgi.server(listener, hello_world)

if __name__ == '__main__':
    sys.exit(main())

Shamelessly taken from: https://www.bountysource.com/issues/32684217-using-both-eventlet-monkey_patch-and-eventlet-wsgi-server-together-with-ssl-fails-with-ssl-sslwantreaderror, but now with different error

Hoffs commented 7 years ago

Similar error while using Requests library, fixed by reverting to 0.17.4 as mentioned.:

2017-02-21T16:56:44.729121+00:00 app[worker1.1]: [2017-02-21 16:56:44,726: ERROR/MainProcess] Task twitch_stats.tasks.get_stats_by_id[9e7eb62b-3fbf-47c9-ab0c-6e02f078bb58] raised unexpected: RecursionError('maximum recursion depth exceeded while calling a Python object',)
2017-02-21T16:56:44.729124+00:00 app[worker1.1]: Traceback (most recent call last):
2017-02-21T16:56:44.729125+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/celery/app/trace.py", line 367, in trace_task
2017-02-21T16:56:44.729126+00:00 app[worker1.1]:     R = retval = fun(*args, **kwargs)
2017-02-21T16:56:44.729126+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/celery/app/trace.py", line 622, in __protected_call__
2017-02-21T16:56:44.729127+00:00 app[worker1.1]:     return self.run(*args, **kwargs)
2017-02-21T16:56:44.729128+00:00 app[worker1.1]:   File "/app/twitch_stats/tasks.py", line 34, in get_stats_by_id
2017-02-21T16:56:44.729129+00:00 app[worker1.1]:     TwitchStats.objects.get_stats(twitch_id=tid)
2017-02-21T16:56:44.729130+00:00 app[worker1.1]:   File "/app/twitch_stats/managers.py", line 160, in get_stats
2017-02-21T16:56:44.729130+00:00 app[worker1.1]:     r = requests.get(url=url, headers=headers)
2017-02-21T16:56:44.729132+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/api.py", line 70, in get
2017-02-21T16:56:44.729132+00:00 app[worker1.1]:     return request('get', url, params=params, **kwargs)
2017-02-21T16:56:44.729133+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/api.py", line 56, in request
2017-02-21T16:56:44.729134+00:00 app[worker1.1]:     return session.request(method=method, url=url, **kwargs)
2017-02-21T16:56:44.729134+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/sessions.py", line 488, in request
2017-02-21T16:56:44.729135+00:00 app[worker1.1]:     resp = self.send(prep, **send_kwargs)
2017-02-21T16:56:44.729136+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/sessions.py", line 609, in send
2017-02-21T16:56:44.729137+00:00 app[worker1.1]:     r = adapter.send(request, **kwargs)
2017-02-21T16:56:44.729137+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/adapters.py", line 423, in send
2017-02-21T16:56:44.729138+00:00 app[worker1.1]:     timeout=timeout
2017-02-21T16:56:44.729139+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 600, in urlopen
2017-02-21T16:56:44.729140+00:00 app[worker1.1]:     chunked=chunked)
2017-02-21T16:56:44.729141+00:00 app[worker1.1]:     self._validate_conn(conn)
2017-02-21T16:56:44.729141+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 345, in _make_request
2017-02-21T16:56:44.729142+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 844, in _validate_conn
2017-02-21T16:56:44.729143+00:00 app[worker1.1]:     conn.connect()
2017-02-21T16:56:44.729143+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/packages/urllib3/connection.py", line 314, in connect
2017-02-21T16:56:44.729144+00:00 app[worker1.1]:     cert_reqs=resolve_cert_reqs(self.cert_reqs),
2017-02-21T16:56:44.729145+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/site-packages/requests/packages/urllib3/util/ssl_.py", line 264, in create_urllib3_context
2017-02-21T16:56:44.729146+00:00 app[worker1.1]:     context.options |= options
2017-02-21T16:56:44.729146+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/ssl.py", line 459, in options
2017-02-21T16:56:44.729148+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/ssl.py", line 459, in options
2017-02-21T16:56:44.729147+00:00 app[worker1.1]:     super(SSLContext, SSLContext).options.__set__(self, value)
2017-02-21T16:56:44.729149+00:00 app[worker1.1]:   File "/app/.heroku/python/lib/python3.6/ssl.py", line 459, in options
2017-02-21T16:56:44.729148+00:00 app[worker1.1]:     super(SSLContext, SSLContext).options.__set__(self, value)
2017-02-21T16:56:44.729149+00:00 app[worker1.1]:     super(SSLContext, SSLContext).options.__set__(self, value)
2017-02-21T16:56:44.729150+00:00 app[worker1.1]:   [Previous line repeated 109 more times]
2017-02-21T16:56:44.729151+00:00 app[worker1.1]:   File "...", line -1, in [rest of traceback truncated]
2017-02-21T16:56:44.729200+00:00 app[worker1.1]: RecursionError: maximum recursion depth exceeded while calling a Python object
j-walker23 commented 7 years ago

Hi all, what is needed to get new eventlet versions working with python 3.6, either on the python side or eventlet side?

temoto commented 7 years ago

Try to uninstall pyopenssl if possible, please say if it helps.

temoto commented 7 years ago

@j-walker23 @Hoffs- @Renmusxd please try pip uninstall pyopenssl and tell if it helps.

Heanthor commented 7 years ago

I'm having this same problem as well, but PyOpenSSL is not installed. Also using Flask 0.12, Flask-SocketIO 2.8.6.

temoto commented 7 years ago

@Heanthor thank you.

j-walker23 commented 7 years ago

Thanks for the replies! I will test on my gce box running ubuntu and report back.

j-walker23 commented 7 years ago

@temoto I actually didn't have pyopenssl installed either. Should I only be trying eventlet 0.17.4?

temoto commented 7 years ago

@j-walker23 I'm sorry old version is the only workaround right now.

I understand this is an important issue but haven't find solution yet.

j-walker23 commented 7 years ago

@temoto no problem at all. just was curious because i seem to be able to run the latest eventlet on my mac with py36. but when deployed on ubuntu it has this error so i assumed i was just screwing it up. Thank you, really appreciate the lib!

justdoit0823 commented 7 years ago

The ssl module of Python3.6 has made variable options, verify_flags, verify_mode of SSLContext as property, so setting value of the specified property caused function recursively call after eventlet monkey patch. The following code can be found in Python3.6 ssl module.

@property
def options(self):
    return Options(super().options)

@options.setter
def options(self, value):
    super(SSLContext, SSLContext).options.__set__(self, value)

@property
def verify_flags(self):
    return VerifyFlags(super().verify_flags)

@verify_flags.setter
def verify_flags(self, value):
    super(SSLContext, SSLContext).verify_flags.__set__(self, value)

@property
def verify_mode(self):
    value = super().verify_mode
    try:
        return VerifyMode(value)
    except ValueError:
        return value

@verify_mode.setter
def verify_mode(self, value):
    super(SSLContext, SSLContext).verify_mode.__set__(self, value)

As gevent's fixup of this issue:

if hasattr(orig_SSLContext.options, 'setter'):
        # In 3.6, these became properties. They want to access the
        # property __set__ method in the superclass, and they do so by using
        # super(SSLContext, SSLContext). But we rebind SSLContext when we monkey
        # patch, which causes infinite recursion.
        # https://github.com/python/cpython/commit/328067c468f82e4ec1b5c510a4e84509e010f296
        @orig_SSLContext.options.setter
        def options(self, value):
            super(orig_SSLContext, orig_SSLContext).options.__set__(self, value)

        @orig_SSLContext.verify_flags.setter
        def verify_flags(self, value):
            super(orig_SSLContext, orig_SSLContext).verify_flags.__set__(self, value)

        @orig_SSLContext.verify_mode.setter
        def verify_mode(self, value):
            super(orig_SSLContext, orig_SSLContext).verify_mode.__set__(self, value)

Insert if statement in SSLContext definition and decorate set property function.

temoto commented 7 years ago

@justdoit0823 thanks a lot!

temoto commented 7 years ago

Everybody, please, try this version.

pip install https://github.com/eventlet/eventlet/archive/de06878e5a295bfbbddca0048c3453d16168a676.zip

temoto commented 7 years ago

@richardasaurus that's very strange, please show full terminal session how you got it.

temoto commented 7 years ago

Hey guys, the fix was released on PyPI as v0.21.0. Please tell me if it helps.

j-walker23 commented 7 years ago

Awesome, thank you!

temoto commented 7 years ago

@richardasaurus well show everything related to this error from deployment. I can only help knowing how to reproduce the problem.

daviskirk commented 7 years ago

I can confirm that 0.21.0 fixes the eventlet / requests issue. Can't seem to reproduce the compile error @richardasaurus has.

benkuhn commented 7 years ago

I'm still seeing a similar error on eventlet 0.21.0 due to some kind of incredibly bizarre interaction with logging to the root logger at toplevel: https://github.com/benkuhn/eventlet-repro

temoto commented 7 years ago

@benkuhn thank you very much for reproduction repo. Please post python -V.

benkuhn commented 7 years ago
$ python -V
Python 3.6.1

I've pushed an even more minimal repro. Still working on minimizing further. Note that it may be related to newrelic vendoring an old urllib version.

ahartoto commented 7 years ago

Hi, I see this error when I used boto3 functionality. Do we have any fix that I can try out?

temoto commented 7 years ago

@ahartoto not yet.

richmondwang commented 7 years ago

Any workaround for now? I cant use 0.17.4 because I get sqlalchemy.orm.exc.DetachedInstanceError

temoto commented 7 years ago

@ahartoto @richmondwang please try pip install -U 'newrelic>=2.86.3.70' worked for me

richmondwang commented 7 years ago

I did pip install -U 'newrelic>=2.86.3.70' but still the same. I use python36, and with same requirements as OP's.

temoto commented 7 years ago

@richmondwang can you provide reproduce instruction?

dhhagan commented 6 years ago

Is there an update/recommendation on how to bypass this issue with the most up-to-date versions of eventlet and python3.6.3?

dhhagan commented 6 years ago

@richardasaurus Ahh thanks. It appears it was an issue with where I used monkey_patch(), which I moved to the very top of my project file after reading this best practices list.

xuhuigithub commented 6 years ago

Hi, everybody, I found the resolution there.https://github.com/gevent/gevent/issues/941

iamareebjamal commented 4 years ago

Edit: gunicorn preload mode is incompatible with monkey patching, so using normal mode works without issues

Still occurring in Python 3.7, tested on latest code from git

  File "/home/iamareebjamal/git/open-event-server/.venv/lib/python3.7/site-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/home/iamareebjamal/git/open-event-server/.venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 677, in urlopen
    chunked=chunked,
  File "/home/iamareebjamal/git/open-event-server/.venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 381, in _make_request
    self._validate_conn(conn)
  File "/home/iamareebjamal/git/open-event-server/.venv/lib/python3.7/site-packages/urllib3/connectionpool.py", line 976, in _validate_conn
    conn.connect()
  File "/home/iamareebjamal/git/open-event-server/.venv/lib/python3.7/site-packages/urllib3/connection.py", line 344, in connect
    cert_reqs=resolve_cert_reqs(self.cert_reqs),
  File "/home/iamareebjamal/git/open-event-server/.venv/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 276, in create_urllib3_context
    context.options |= options
  File "/home/iamareebjamal/.pyenv/versions/3.7.7/lib/python3.7/ssl.py", line 518, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/home/iamareebjamal/.pyenv/versions/3.7.7/lib/python3.7/ssl.py", line 518, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/home/iamareebjamal/.pyenv/versions/3.7.7/lib/python3.7/ssl.py", line 518, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  [Previous line repeated 468 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object
HyperCharlie commented 4 years ago

Just wanted to chime in that we are currently fighting this issue too. Python 3.6, eventlet 0.25.2, and flask-SocketIO 4.2.1. Mysteriously started producing this issue on 7/17/2020, after a successful deploy on 7/16/2020. Same code, new container build. Best we can tell one of the second-layer dependencies upgraded and it was not locked in our requirements.txt. We're still trying to sort it out. We did what miguelgrinberg recommended and swapped to gevent for testing purposes, and while that does not run into the issue above, there are other issues with gevent that prevent us from using this option. GEvent brings along a different WSGI server (pywsgi) which does not handle the Flask request object the same as Eventlet, notably request.stream is no longer an IOBase compatible steam but instead only a very limited version. The pywsgi.Input object is not compatible with some other streams libraries we're using (Google's resumeable file uploads, notably), and has bugs when dealing with files larger than 2GiB, which we deal with regularly. These issues seem more intractable than the eventlet issue. I'll post an update when we discover the working magic formula.

iamareebjamal commented 4 years ago

@HyperCharlie Are you using gunicorn? Or preload configuration? If so, try without preload

HyperCharlie commented 4 years ago

We are not using gunicorn; we're starting the script directly in a main.py with import eventlet/monkey_patch() being the first two lines. Thanks for the idea though!

I was able to make it work again by pulling a complete requirements.txt from the working image (Python 3.6.9). Here it is for future reference, confirmed working combination of eventlet, python, and flask-socketio:

absl-py==0.7.1
aioredis==1.3.1
aioredlock==0.5.2
alabaster==0.7.12
aniso8601==7.0.0
apache-libcloud==2.8.1
APScheduler==3.6.3
argh==0.26.2
asn1crypto==0.24.0
astroid==2.4.2
async-timeout==3.0.1
atomicwrites==1.4.0
attrdict==2.0.0
attrs==19.1.0
Authlib==0.14.1
backcall==0.2.0
behave==1.2.6
boto3==1.11.3
botocore==1.14.17
cachetools==2.1.0
certifi==2019.3.9
cffi==1.12.2
chardet==3.0.4
Click==7.0
cloudpickle==0.8.0
colorama==0.4.1
coverage==4.5.4
cryptography==2.6.1
cytoolz==0.9.0.1
decorator==4.4.0
Deprecated==1.2.7
dill==0.2.9
dnspython==1.16.0
docutils==0.15.2
ecdsa==0.13
eth-abi==1.3.0
eth-account==0.3.0
eth-hash==0.2.0
eth-keyfile==0.5.1
eth-keys==0.2.4
eth-rlp==0.1.2
eth-typing==2.2.1
eth-utils==1.9.0
eventemitter==0.2.0
eventlet==0.25.2
Flask==1.1.1
Flask-APScheduler==1.11.0
Flask-Cors==3.0.7
Flask-Injector==0.12.0
flask-io==1.14.2
Flask-Login==0.4.1
flask-redis==0.4.0
Flask-SocketIO==4.2.1
Flask-SQLAlchemy==2.4.1
flask-talisman==0.6.0
future==0.17.1
gast==0.2.2
google-api-core==1.16.0
google-api-python-client==1.7.6
google-auth==1.11.0
google-auth-httplib2==0.0.3
google-cloud==0.34.0
google-cloud-core==1.3.0
google-cloud-datastore==1.7.0
google-cloud-storage==1.25.0
google-resumable-media==0.5.0
googleapis-common-protos==1.51.0
gprof2dot==2019.11.30
graphene==2.1.8
graphene-sqlalchemy==2.2.2
graphql-core==2.2.1
graphql-relay==2.0.1
greenlet==0.4.15
grpcio==1.15.0
gunicorn==19.9.0
hexbytes==0.1.0
hiredis==1.1.0
httplib2==0.18.1
idna==2.8
importlib-metadata==1.7.0
injector==0.18.3
ipython==7.16.1
ipython-genutils==0.2.0
isort==4.3.21
itsdangerous==0.24
jedi==0.13.3
Jinja2==2.10.1
jmespath==0.10.0
jsonpickle==1.0
jsonschema==3.0.1
lazy-object-proxy==1.4.3
line-profiler==3.0.2
lru-dict==1.1.6
Mako==1.1.0
MarkupSafe==1.1.1
marshmallow==2.21.0
mccabe==0.6.1
monotonic==1.5
more-itertools==8.4.0
newrelic==5.0.2.126
oauth2client==4.1.3
objectmapper==0.0.4
packaging==20.4
parse==1.15.0
parse-type==0.5.2
parsimonious==0.8.0
parso==0.7.0
pexpect==4.8.0
pickleshare==0.7.5
pluggy==0.13.1
promise==2.3
prompt-toolkit==3.0.5
protobuf==3.6.1
psutil==5.6.1
ptyprocess==0.6.0
py==1.9.0
pyasn1==0.4.4
pyasn1-modules==0.2.2
pycodestyle==2.5.0
pycparser==2.19
pycryptodome==3.9.8
pyflakes==2.1.1
Pygments==2.3.1
pylibmc==1.6.1
pylint==2.3.1
PyMySQL==0.9.2
pyparsing==2.3.1
pyrsistent==0.14.11
pysha3==1.0.2
PySocks==1.6.8
pytest==5.0.1
pytest-asyncio==0.10.0
pytest-profiling==1.7.0
python-dateutil==2.8.0
python-dotenv==0.10.1
python-engineio==3.9.3
python-etcd==0.4.5
python-jose-cryptodome==1.3.2
python-redis-lock==3.5.0
python-socketio==4.5.1
pytictoc==1.5.0
pytz==2020.1
redis==3.3.5
requests==2.23.0
rlp==1.0.3
rq==1.1.0
rsa==4.0
Rx==1.6.1
s3transfer==0.3.3
sherlock==0.3.2
singledispatch==3.4.0.3
six==1.12.0
snowballstemmer==1.2.1
socketIO-client==0.7.2
SQLAlchemy==1.3.10
sqlalchemy-json==0.2.2
SQLAlchemy-Utils==0.33.6
stripe==2.48.0
termcolor==1.1.0
toolz==0.10.0
traitlets==4.3.3
typed-ast==1.4.1
typing==3.7.4.3
typing-extensions==3.7.4.2
tzlocal==2.1
uritemplate==3.0.0
urllib3==1.24.1
wcwidth==0.2.5
web3==4.7.2
websocket-client==0.57.0
websockets==6.0
Werkzeug==0.15.5
wrapt==1.12.1
zipp==3.1.0
emmanueljob commented 4 years ago

@HyperCharlie had the same issue. dnspython was the issue: 1.1.16 works 2.0.0 causes this issue.

DanielVZ96 commented 4 years ago

@emmanueljob Can confirm that downgrading dnspython works, but the version is 1.16.0 ;)

root@46c45698353e:/# pip install dnspython==1.1.16
ERROR: Could not find a version that satisfies the requirement dnspython==1.1.16 (from versions: 1.11.0, 1.11.1, 1.12.0, 1.13.0, 1.14.0, 1.15.0, 1.16.0, 2.0.0rc1, 2.0.0rc2, 2.0.0)
ERROR: No matching distribution found for dnspython==1.1.16

root@46c45698353e:/# pip install dnspython==1.16.0
Collecting dnspython==1.16.0
  Downloading dnspython-1.16.0-py2.py3-none-any.whl (188 kB)
     |████████████████████████████████| 188 kB 3.2 MB/s 
Installing collected packages: dnspython
Successfully installed dnspython-1.16.0
gsilvapt commented 4 years ago

In another project, we had to downgrade to version 1.16.0 for this to work.

jjedele commented 3 years ago

What is the current state of this issue? I'm running into the same issue with Python 3.6.9 and eventlet 0.30.0. Had to downgrade to 0.17.4 for it to work (dnspython-1.16.0 installed, this was not the issue apparently).

mattbennett commented 3 years ago

This can be a symptom of several different problems, I think.

For folks who are still experiencing it even with dnspython<2, check that nothing is importing requests before the monkey patch is applied.

miquelvir commented 2 years ago

What is the status of this?

asyncmind0 commented 2 years ago

Replicated on: Eventlet Version: 0.33.0 Python version: 3.10.2, 3.9.10

  File "/usr/local/lib/python3.9/site-packages/urllib3/poolmanager.py", line 375, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 703, in urlopen
    httplib_response = self._make_request(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 386, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1040, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.9/site-packages/urllib3/connection.py", line 397, in connect
    self.ssl_context = create_urllib3_context(
  File "/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 312, in create_urllib3_context
    context.options |= options
  File "/usr/local/lib/python3.9/site-packages/eventlet/green/ssl.py", line 458, in options
    super(_original_sslcontext, _original_sslcontext).options.__set__(self, value)
  File "/usr/local/lib/python3.9/ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/usr/local/lib/python3.9/ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  File "/usr/local/lib/python3.9/ssl.py", line 602, in options
    super(SSLContext, SSLContext).options.__set__(self, value)
  [Previous line repeated 433 more times]
dankingtech commented 1 year ago

I seem to be having a similar issue, and would like to know whether it is related. I have narrowed down the replication to using requests.get() after monkey_patch for sockets.

Here is the replication:

$ podman run --rm -it python:3.9 bash
root@f7333769f4da:/# pip install -U pip requests eventlet
...
root@f7333769f4da:/# python
Python 3.9.17 (main, Jul 28 2023, 05:54:52) 
[GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import eventlet
>>> import requests
>>> eventlet.monkey_patch(all=False, socket=True)
>>> requests.get('https://google.com/')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 73, in get
    return request("get", url, params=params, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/requests/adapters.py", line 486, in send
    resp = conn.urlopen(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 790, in urlopen
    response = self._make_request(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 467, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py", line 1092, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.9/site-packages/urllib3/connection.py", line 642, in connect
    sock_and_verified = _ssl_wrap_socket_and_match_hostname(
  File "/usr/local/lib/python3.9/site-packages/urllib3/connection.py", line 735, in _ssl_wrap_socket_and_match_hostnam
e
    context = create_urllib3_context(
  File "/usr/local/lib/python3.9/site-packages/urllib3/util/ssl_.py", line 292, in create_urllib3_context
    context.minimum_version = TLSVersion.TLSv1_2
  File "/usr/local/lib/python3.9/ssl.py", line 587, in minimum_version
    super(SSLContext, SSLContext).minimum_version.__set__(self, value)
  File "/usr/local/lib/python3.9/ssl.py", line 587, in minimum_version
    super(SSLContext, SSLContext).minimum_version.__set__(self, value)
  File "/usr/local/lib/python3.9/ssl.py", line 587, in minimum_version
    super(SSLContext, SSLContext).minimum_version.__set__(self, value)
  [Previous line repeated 491 more times]
RecursionError: maximum recursion depth exceeded
>>> 

And here is the list of package versions from pip:

root@f7333769f4da:/# pip list
Package            Version
------------------ ---------
certifi            2023.7.22
charset-normalizer 3.2.0
dnspython          2.4.2
eventlet           0.33.3
greenlet           2.0.2
idna               3.4
pip                23.2.1
requests           2.31.0
setuptools         58.1.0
six                1.16.0
urllib3            2.0.4
wheel              0.41.1
root@f7333769f4da:/#
van4oza commented 10 months ago

Hi!

Same here

mb Timeout involved

def scrap(row_data: dict) -> (dict, Exception):
    try:
        with eventlet.timeout.Timeout(60*30, False):
            ...
            return smth
        raise Exception("eventlet timeout")
    except Exception as e:
        return row_data, e

for result, exc in pool.imap(scrap, [...]):
    pass
Exception ignored in: <function GreenSocket.__del__ at 0x1026e5d30>
Traceback (most recent call last):
  File "/Users/van4oza/PycharmProjects/enterprise_app/venv/lib/python3.8/site-packages/eventlet/greenio/base.py", line 241, in __del__
    close = getattr(self, 'close', None)
RecursionError: maximum recursion depth exceeded while calling a Python object
Fatal Python error: Cannot recover from stack overflow.
Python runtime state: initialized

Current thread 0x00000001dfe91e00 (most recent call first):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 602 in options
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 602 in options
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/ssl.py", line 602 in options
...etc.

Python 3.8

aiohttp==3.8.4
aiosignal==1.3.1
appdirs==1.4.3
asgiref==3.7.2
async-timeout==4.0.2
atomicwrites==1.4.1
attrs==23.1.0
Authlib==0.15.6
backports-abc==0.5
backports.ssl-match-hostname==3.5.0.1
backports.zoneinfo==0.2.1
beautifulsoup4==4.12.2
black==22.3.0
blessed==1.14.2
blessings==1.7
boto==2.42.0
boto3==1.28.77
botocore==1.31.77
bpython==0.16
Brotli==1.0.9
bs4==0.0.1
cachetools==5.3.1
cement==2.8.2
certifi==2018.4.16
cffi==1.15.1
cfgv==3.3.1
cfn-flip==1.2.3
chardet==3.0.4
charset-normalizer==3.1.0
click==8.0.1
clickhouse-cityhash==1.0.2.4
clickhouse-driver==0.2.6
colorama==0.3.7
coreapi==2.3.3
coreschema==0.0.4
coverage==3.7.1
cryptography==3.4.8
cssselect==1.2.0
curtsies==0.2.11
dataclasses-json==0.5.9
defusedxml==0.7.1
distlib==0.3.6
dj-database-url==0.4.1
dj-static==0.0.6
Django==3.2
django-braces==1.11.0
django-cors-headers==3.14.0
django-dbconn-retry==0.1.7
django-extensions==1.7.7
django-multiselectfield==0.1.12
django-s3direct==0.4.2
django-storages==1.5.0
django-unixdatetimefield==0.1.6
djangorestframework==3.14.0
dnspython==2.3.0
docker-py==1.7.2
dockerpty==0.4.1
docopt==0.6.2
docutils==0.13.1
ecdsa==0.10
editdistance==0.5.3
elasticsearch==7.13.4
elasticsearch-dsl==7.1.0
eventlet==0.33.3
Fabric==1.8.2
fake-useragent==1.1.3
feedparser==6.0.10
ffmpeg-python @ git+https://github.com/kkroening/ffmpeg-python@df129c7ba30aaa9ffffb81a48f53aa7253b0b4e6
filelock==3.12.2
flake8==4.0.1
foreman==0.9.7
free-proxy==1.0.6
frozenlist==1.3.3
future==0.18.3
fuzzysearch==0.7.3
fuzzywuzzy==0.18.0
gender-guesser==0.2.0
geoip2==4.5.0
google-api-core==2.10.1
google-api-python-client==2.81.0
google-auth==2.21.0
google-auth-httplib2==0.1.0
google-auth-oauthlib==1.0.0
googleapis-common-protos==1.56.4
greenlet==0.4.15
gunicorn==19.3.0
haversine==2.8.0
html2text==2020.1.16
htmlmin==0.1.12
httplib2==0.18.1
identify==2.5.24
idna==2.6
ifaddr==0.2.0
importlib-metadata==4.13.0
importlib-resources==5.12.0
IP2Location==8.9.0
iso8601==2.0.0
isodate==0.6.1
itsdangerous==0.23
itypes==1.1.0
Jinja2==2.9.6
jmespath==0.9.3
joblib==1.3.1
kappa==0.6.0
keyring==10.3.2
keyrings.alt==2.2
librespot==0.0.9
lxml==4.5.0
lz4==4.3.2
m3u8==1.0.0
MarkupSafe==1.1.1
marshmallow==3.19.0
marshmallow-enum==1.5.1
maxminddb==2.4.0
mccabe==0.6.1
mongoengine==0.20.0
more-itertools==8.13.0
multidict==6.0.4
mutagen==1.46.0
mypy-extensions==1.0.0
nltk==3.7
nodeenv==1.8.0
numpy==1.24.4
oauth2==1.9.0.post1
oauth2client==4.1.3
oauthlib==2.0.7
packaging==23.1
pandas==2.0.3
paramiko==1.12.2
parse==1.19.1
pathlib-mate==1.2.1
pathspec==0.9.0
placebo==0.10.0
platformdirs==3.8.0
podcastparser==0.6.4
pre-commit==2.18.1
prettytable==3.8.0
progress==1.6
protobuf==3.20.1
psycopg2-binary==2.9.2
pyasn1==0.5.0
pyasn1-modules==0.3.0
pycodestyle==2.8.0
pycparser==2.21
pycrypto==2.6.1
pycryptodome==3.18.0
pycryptodomex==3.17
pyee==8.2.2
pyflakes==2.4.0
Pygments==2.2.0
pygsheets==2.0.5
PyJWT==1.6.1
pymongo==3.13.0
PyOgg==0.6.14a1
pyparsing==2.2.0
pyppeteer==0.2.6
pyquery==2.0.0
python-dateutil==2.8.2
python-http-client==3.3.7
python-Levenshtein==0.12.2
python-social-auth==0.3.6
python-twitter==3.5
python-twitter-v2==0.8.1
python3-openid==3.1.0
pytz==2022.4
PyYAML==6.0.1
RandomWords==0.2.1
regex==2023.6.3
requests==2.30.0
requests-aws4auth==0.9
requests-futures==0.9.7
requests-html==0.10.0
requests-oauthlib==0.8.0
rsa==4.9
s3transfer==0.7.0
selenium==3.141.0
semantic-version==2.5.0
sendgrid==6.1.2
sentry-sdk==1.31.0
sgmllib3k==1.0.0
singledispatch==3.4.0.3
six==1.15.0
slackclient==2.9.3
social-auth-app-django==2.1.0
social-auth-core==1.7.0
soupsieve==2.4.1
SQLAlchemy==1.4.49
sqlalchemy-mate==1.4.28.4
sqlparse==0.4.4
static3==0.7.0
tabulate==0.7.5
termcolor==1.1.0
timeout-decorator==0.5.0
toml==0.10.2
tomli==2.0.1
tornado==6.0.3
tqdm==4.65.0
twitch-dl==1.21.0
typing-inspect==0.9.0
typing_extensions==4.7.1
tzdata==2023.3
tzlocal==5.0.1
uritemplate==4.1.1
urllib3==1.26.16
uszipcode==1.0.1
virtualenv==20.0.8
w3lib==2.1.1
wcwidth==0.1.7
websocket-client==1.5.1
websockets==9.1
Werkzeug==0.9.4
WTForms==1.0.5
yarl==1.9.2
yt-dlp==2023.7.6
zeroconf==0.62.0
zipp==3.15.0
zstd==1.5.5.1
bbebse2 commented 1 month ago

The issue can be solved by the following patch.

def _green_socket_modules():
    from eventlet.green import socket
    return [('socket', socket)]

import eventlet.patcher
eventlet.patcher.__dict__['_green_socket_modules'] = _green_socket_modules
4383 commented 1 month ago

@bbebse2 Do you want to propose a pull request?

azhengzz commented 5 days ago

The issue can be solved by the following patch.

def _green_socket_modules():
    from eventlet.green import socket
    return [('socket', socket)]

import eventlet.patcher
eventlet.patcher.__dict__['_green_socket_modules'] = _green_socket_modules

Thasks @bbebse2, It works for me.

Python 3.9.2

Package                Version
---------------------- ------------
alembic                1.12.1      
APScheduler            3.10.4      
bcrypt                 4.1.2       
bidict                 0.22.1      
blinker                1.7.0       
Bootstrap-Flask        2.3.2       
certifi                2023.11.17  
cffi                   1.16.0      
chardet                3.0.4       
charset-normalizer     3.3.2       
click                  8.1.7       
colorama               0.4.6       
concurrent-log-handler 0.9.24      
cryptography           41.0.7      
dnspython              2.5.0       
email-validator        2.1.0.post1 
eventlet               0.33.3      
Flask                  3.0.0       
Flask-Login            0.6.3       
Flask-Mail             0.9.1       
Flask-Migrate          4.0.5       
Flask-SocketIO         5.3.6       
Flask-SQLAlchemy       3.1.1       
Flask-WTF              1.2.1       
greenlet               1.1.1
h11                    0.14.0
idna                   2.10
importlib-metadata     6.8.0
itsdangerous           2.1.2
Jinja2                 3.1.2
lxml                   5.1.0
Mako                   1.2.4
MarkupSafe             2.1.3
monotonic              1.6
paramiko               3.4.0
pip                    23.3.1
pipdeptree             2.13.0
portalocker            2.8.2
pycparser              2.21
PyJWT                  2.8.0
PyMySQL                1.1.0
PyNaCl                 1.5.0
python-engineio        4.8.0
python-socketio        5.10.0
pytz                   2023.3.post1
pywin32                306
requests               2.31.0
requests-toolbelt      1.0.0
setuptools             49.2.1
simple-websocket       1.0.0
six                    1.16.0
SQLAlchemy             2.0.23
typing_extensions      4.8.0
tzdata                 2023.3
tzlocal                5.2
urllib3                1.25.11
Werkzeug               3.0.1
wsproto                1.2.0
WTForms                3.1.1
zipp                   3.17.0