Skip to content

Instantly share code, notes, and snippets.

@dhable
Last active November 12, 2015 17:33
Show Gist options
  • Save dhable/74122434b7c8abef42f3 to your computer and use it in GitHub Desktop.
Save dhable/74122434b7c8abef42f3 to your computer and use it in GitHub Desktop.
"""
Check out the differences between the select.poll functionality in CPython
and Jython.
"""
import socket
import errno
import threading
import traceback
import logging
import select
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('select_bug')
class SocketPollThread(threading.Thread):
def __init__(self, address, name):
threading.Thread.__init__(self, name=name)
self.address = address
self.connect_status_results = []
self.final_result = ""
self.poller = select.poll()
def run(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(0)
try:
connect_errno = sock.connect_ex(self.address)
if connect_errno != errno.EINPROGRESS:
self.final_result = "[%s] socket did not enter EINPROGRESS as expected" % (self.getName(),)
return
else:
self.poller.register(sock.fileno())
fd_map = {sock.fileno(): sock}
while True:
events = self.poller.poll()
for fd, event in events:
logger.debug("sock.fileno = " + str(sock.fileno()) + ", fd = " + str(fd))
if sock.fileno() == fd:
self.final_result = "fd and sock.fileno() values match"
else:
self.final_result = "FAIL: fd and sock.fileno() values differ"
return
except:
self.final_result = traceback.format_exc()
finally:
try:
sock.shutdown(0)
sock.shutdown(1)
sock.close()
except:
pass
if __name__ == "__main__":
t = SocketPollThread(address=('127.0.0.1', 8000), name="SelectTest-1")
t.start()
t.join()
logger.debug(t.final_result)
@dhable
Copy link
Author

dhable commented Nov 11, 2015

vagrant@vagrant-ubuntu-trusty-64:/vagrant_data$ uname -a
Linux vagrant-ubuntu-trusty-64 3.13.0-52-generic #86-Ubuntu SMP Mon May 4 04:32:59 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
vagrant@vagrant-ubuntu-trusty-64:/vagrant_data$ python -m SimpleHTTPServer 8000 &
vagrant@vagrant-ubuntu-trusty-64:/vagrant_data$ Serving HTTP on 0.0.0.0 port 8000 ...
[1] 26047

vagrant@vagrant-ubuntu-trusty-64:/vagrant_data$ python jython_select_bug.py
DEBUG:select_bug:sock.fileno = 3, fd = 3
DEBUG:select_bug:fd and sock.fileno() values match

vagrant@vagrant-ubuntu-trusty-64:/vagrant_data$ java -jar jython-standalone-2.7.1b2.jar jython_select_bug.py
DEBUG:select_bug:sock.fileno = <_realsocket at 0x2 type=client open_count=1 channel=[id: 0x7d79f1d2] timeout=0.0>, fd = <_socket._socketobject object at 0x3>
DEBUG:select_bug:FAIL: fd and sock.fileno() values differ```

@dhable
Copy link
Author

dhable commented Nov 12, 2015

NOTE - I originally thought this was a bug in the Jython poll impl but instead was a misuse of the API. poll.register accepts a fd that needs to be obtained by calling fileno() on a socket, file object, etc.

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