Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GreenSocket conflict with pysocks #616

Closed
terryzhu opened this issue Jun 18, 2020 · 5 comments
Closed

GreenSocket conflict with pysocks #616

terryzhu opened this issue Jun 18, 2020 · 5 comments

Comments

@terryzhu
Copy link

terryzhu commented Jun 18, 2020

Combine eventlet and pysocks, it will cause RecursionError: maximum recursion depth exceeded

Code example

import eventlet
eventlet.monkey_patch()

import socket
import socks

def test_block_connect():
    s = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('example.com', 80))

gt = eventlet.spawn(test_block_connect)
gt.wait()

Actual behaviour

Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/eventlet/hubs/hub.py", line 461, in fire_timers
    timer()
  File "/usr/lib/python3.6/site-packages/eventlet/hubs/timer.py", line 59, in __call__
    cb(*args, **kw)
  File "/usr/lib/python3.6/site-packages/eventlet/greenthread.py", line 221, in main
    result = function(*args, **kwargs)
  File "eventlet_sample.py", line 10, in test_block_connect
    s.connect(('example.com', 80))
  File "/usr/lib/python3.6/site-packages/socks.py", line 47, in wrapper
    return function(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/socks.py", line 774, in connect
    super(socksocket, self).settimeout(self._timeout)
  File "/usr/lib/python3.6/site-packages/eventlet/greenio/base.py", line 418, in settimeout
    self.setblocking(True)
  File "/usr/lib/python3.6/site-packages/socks.py", line 296, in setblocking
    self.settimeout(None)
  File "/usr/lib/python3.6/site-packages/socks.py", line 287, in settimeout
    super(socksocket, self).settimeout(self._timeout)
.....
.....
.....
.....
  File "/usr/lib/python3.6/site-packages/eventlet/greenio/base.py", line 418, in settimeout
    self.setblocking(True)
  File "/usr/lib/python3.6/site-packages/socks.py", line 296, in setblocking
    self.settimeout(None)
RecursionError: maximum recursion depth exceeded

Root cause

GreenSocket settimeout will call setblocking, it will call pysocks setblocking, it will call GrenSocket settimeout again, infinitely.

@leoch20
Copy link

leoch20 commented Jul 2, 2020

Same here

@greenfrogs
Copy link

I am having the same problem with gunicorn, has anyone found a workaround?

@terryzhu
Copy link
Author

I am having the same problem with gunicorn, has anyone found a workaround?

If you can modify the source code after you install pysocks, maybe you could add the following logic:
original code:

def setblocking(self, v):
    if v:
        self.settimeout(None)
    else:
        self.settimeout(0.0)

Modified to:

def setblocking(self, v):
    if self._timeout == v:
        return
    if v:
        self.settimeout(None)
    else:
        self.settimeout(0.0)

To break the recursive method invoking

@temoto
Copy link
Member

temoto commented Oct 20, 2020

@terryzhu sorry. Usually we have a policy "if it works in vanilla Python then it's a bug in Eventlet". In this case IMHO they (ab)used setblocking/settimeout API in wrong way.

If someone comes up with a patch that could fix this on eventlet side, I'd be happy to know, please reopen. But so far it doesn't seem possible to me. Sorry.

As workaround, you may use older version of pysocks.

@temoto temoto closed this as completed Oct 20, 2020
@temoto
Copy link
Member

temoto commented Oct 20, 2020

Watch this issue Anorov/PySocks#121

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants