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

Non-blocking behaviour (timeout = 0) is ignored #121

Open
Lonami opened this issue Mar 16, 2019 · 3 comments
Open

Non-blocking behaviour (timeout = 0) is ignored #121

Lonami opened this issue Mar 16, 2019 · 3 comments

Comments

@Lonami
Copy link

Lonami commented Mar 16, 2019

Hello! I'm facing a bit of an issue with PySocks and asyncio together (by using loop.sock_connect). As it turns out, PySocks seems to be ignoring the non-blocking behaviour. This seems to be the cause:

PySocks/socks.py

Lines 94 to 110 in b687a34

def set_self_blocking(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
self = args[0]
try:
_is_blocking = self.gettimeout()
if _is_blocking == 0:
self.setblocking(True)
return function(*args, **kwargs)
except Exception as e:
raise
finally:
# set orgin blocking
if _is_blocking == 0:
self.setblocking(False)
return wrapper

Now, could I get some explanation on why that is needed? Here is the code to reproduce the issue:

import socks
import socket
import time
import asyncio

loop = asyncio.get_event_loop()

async def main():
    s = socks.socksocket(socket.AF_INET)
    #   ^^^^^ replacing "socks" with "socket" works correctly
    # But using "socks" does not work:

    s.setblocking(False)
    start = time.time()
    try:
        # The IP we try to connect to doesn't really matter
        await asyncio.wait_for(
            loop.sock_connect(s, ('1.1.1.1', 1234)),
            timeout=2,
            loop=loop
        )
    except:
        pass
    finally:
        print('Took', time.time() - start)

loop.run_until_complete(main())

The change that introduced this (a2cab50) does not give much information:

fix a error when the socket connect is not blocking
add a Decorator to checking the socket's blocking
@temoto
Copy link

temoto commented Oct 20, 2020

Same problem: eventlet/eventlet#616

@terryzhu suggested this workaround

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

I think, pysocks should use existing get/settimeout and don't touch blocking behavior at all. Sorry, don't have time for proper solution right now.

@qkn
Copy link

qkn commented Mar 4, 2021

any fix for this?

@Lonami
Copy link
Author

Lonami commented Mar 4, 2021

I no longer depend on PySocks, asyncio-native proxy libraries exist. I won't promote it here, but you can find the one I use on the optional requirements for the library behind the first link I posted.

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

No branches or pull requests

3 participants