gevent icon indicating copy to clipboard operation
gevent copied to clipboard

Resoult of select.select was wrong when monkey patched with loop 'libuv'

Open SeaHOH opened this issue 4 years ago • 1 comments

  • gevent version: 21.1.2 from PyPI
  • Python version: cPython 3.8.8 embed downloaded from python.org
  • Operating System: Windows 7 SP1 64bit

Description:

I use select.select to observe readable status, once after received some data, then select.select still return readable even no data can be readed.

No tracebacks, it just blocked the code. I has wrote some test code use assert, you will run and see the traceback:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

What I've run:

  • first run a echo server
Python 3.10.1 (tags/v3.10.1:2cd268a, Dec  6 2021, 19:10:37) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import select, socket
>>> s_addr = ('127.0.0.1', 9999)
>>>
>>> s_tcp = socket.socket()
>>> s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s_tcp.bind(s_addr)
>>> s_udp.bind(s_addr)
>>> s_tcp.listen(2)
>>>
>>> while 1:
...     ss = select.select([s_tcp, s_udp], [], [], 1)[0]
...     if ss:
...         s = ss[0]
...         if s is s_tcp:
...             s = s.accept()[0]
...             s.send(s.recv(1024))
...         else:
...             s.sendto(*s.recvfrom(1024))
...
  • gevent monkey patch with loop 'libuv-cffi' is failed
Python 3.10.1 (tags/v3.10.1:2cd268a, Dec  6 2021, 19:10:37) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['GEVENT_LOOP'] = 'libuv-cffi'
>>> import gevent.monkey
>>> gevent.monkey.patch_all()
True
>>> import select, socket
>>> s_addr = ('127.0.0.1', 9999)
>>> d_test = b'test'
>>>
>>> # TCP
>>> s_tcp = socket.socket()
>>> s_tcp.connect(s_addr)
>>> assert any(select.select([s_tcp], [], [], 1)) == False
>>> assert s_tcp.send(d_test) == len(d_test)
>>> assert any(select.select([s_tcp], [], [], 1)) == True
>>> assert s_tcp.recv(len(d_test)) == d_test
>>> assert any(select.select([s_tcp], [], [], 1)) == False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>>
>>> # UDP
>>> s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> assert any(select.select([s_udp], [], [], 1)) == False
>>> assert s_udp.sendto(d_test, s_addr) == len(d_test)
>>> assert any(select.select([s_udp], [], [], 1)) == True
>>> assert s_udp.recvfrom(len(d_test)) == (d_test, s_addr)
>>> assert any(select.select([s_udp], [], [], 1)) == False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>>
  • gevent monkey patch with loop 'libev-cext' is OK
Python 3.10.1 (tags/v3.10.1:2cd268a, Dec  6 2021, 19:10:37) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['GEVENT_LOOP'] = 'libev-cext'
>>> import gevent.monkey
>>> gevent.monkey.patch_all()
True
>>> import select, socket
>>> s_addr = ('127.0.0.1', 9999)
>>> d_test = b'test'
>>>
>>> # TCP
>>> s_tcp = socket.socket()
>>> s_tcp.connect(s_addr)
>>> assert any(select.select([s_tcp], [], [], 1)) == False
>>> assert s_tcp.send(d_test) == len(d_test)
>>> assert any(select.select([s_tcp], [], [], 1)) == True
>>> assert s_tcp.recv(len(d_test)) == d_test
>>> assert any(select.select([s_tcp], [], [], 1)) == False
>>>
>>> # UDP
>>> s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> assert any(select.select([s_udp], [], [], 1)) == False
>>> assert s_udp.sendto(d_test, s_addr) == len(d_test)
>>> assert any(select.select([s_udp], [], [], 1)) == True
>>> assert s_udp.recvfrom(len(d_test)) == (d_test, s_addr)
>>> assert any(select.select([s_udp], [], [], 1)) == False
>>>
  • no gevent monkey patch is OK
Python 3.10.1 (tags/v3.10.1:2cd268a, Dec  6 2021, 19:10:37) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import select, socket
>>> s_addr = ('127.0.0.1', 9999)
>>> d_test = b'test'
>>>
>>> # TCP
>>> s_tcp = socket.socket()
>>> s_tcp.connect(s_addr)
>>> assert any(select.select([s_tcp], [], [], 1)) == False
>>> assert s_tcp.send(d_test) == len(d_test)
>>> assert any(select.select([s_tcp], [], [], 1)) == True
>>> assert s_tcp.recv(len(d_test)) == d_test
>>> assert any(select.select([s_tcp], [], [], 1)) == False
>>>
>>> # UDP
>>> s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> assert any(select.select([s_udp], [], [], 1)) == False
>>> assert s_udp.sendto(d_test, s_addr) == len(d_test)
>>> assert any(select.select([s_udp], [], [], 1)) == True
>>> assert s_udp.recvfrom(len(d_test)) == (d_test, s_addr)
>>> assert any(select.select([s_udp], [], [], 1)) == False
>>>

SeaHOH avatar Mar 20 '21 09:03 SeaHOH

@jamadden A year has passed, do you have any idea? And I have re-wrote the test codes, make it more clear.

SeaHOH avatar Jan 01 '22 21:01 SeaHOH