Skip to content

Instantly share code, notes, and snippets.

@dhable
Last active November 12, 2015 17:33
"""
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