Python: select() returns immediately without no data to read (telnetlib)

1.2k views Asked by At

I want to use select.select() to block the loop until some data is ready to be read from a list of telnet sessions. However, the below code does not work and the call to select.select() returns immediately with no data to read. I'm using python 2.7.3 under Ubuntu 10.4.

tn = telnetlib.Telnet(IP,23,TIMEOUT)
# [... logging and password omitted ..]

while True:
    logging.info("%d - waiting on select for data" % self.id)
    read_ready, write_ready, expt_ready = select.select([ tn.get_socket() ],[],[])
    logging.info("%d - select returned" % self.id)
    if len(read_ready) == 1:
        data = tn.read_eager()
        logging.info("%d read %d characters" % (self.id, len(data)))
        # ... continue processing the data...

An example of the output:

2013-08-23 10:37:28,634 - INFO: 1 - waiting on select for data
2013-08-23 10:37:28,672 - INFO: 1 - select returned
2013-08-23 10:37:28,673 - INFO: 1 read 0 characters
2013-08-23 10:37:28,833 - INFO: 1 - waiting on select for data
2013-08-23 10:37:28,874 - INFO: 1 - select returned
2013-08-23 10:37:28,874 - INFO: 1 read 0 characters
2013-08-23 10:37:29,029 - INFO: 1 - waiting on select for data
2013-08-23 10:37:29,073 - INFO: 1 - select returned
2013-08-23 10:37:29,074 - INFO: 1 read 0 characters

An example with set_debuglevel(1):

2013-08-23 11:50:29,019 - INFO: 1 - waiting on select for data
2013-08-23 11:50:29,062 - INFO: 1 - select returned
Telnet(10.2.3.15,23): recv '\xff\xfe\x01'
Telnet(10.2.3.15,23): IAC DONT 1
2013-08-23 11:50:29,062 - INFO: 1 read 0 characters
2013-08-23 11:50:29,063 - INFO: 1 - waiting on select for data
2013-08-23 11:50:29,069 - INFO: 1 - select returned
Telnet(10.2.3.15,23): recv '\xff\xfe!'
Telnet(10.2.3.15,23): IAC DONT 33
2013-08-23 11:50:29,069 - INFO: 1 read 0 characters
2013-08-23 11:50:29,070 - INFO: 1 - waiting on select for data
2013-08-23 11:50:29,110 - INFO: 1 - select returned
Telnet(10.2.3.15,23): recv '\xff\xfc\x03'
Telnet(10.2.3.15,23): IAC WONT 3
2013-08-23 11:50:29,110 - INFO: 1 read 0 characters
2

There are 2 answers

3
Stefano M On

The answer is in the docs: (pydoc telnetlib):

It is possible to pass a Telnet object to select.select() in order to wait until more data is available. Note that in this case, read_eager() may return '' even if there was data on the socket, because the protocol negotiation may have eaten the data.

As it is clear from the debug output the remote end is sending telnet commands and not actual data, so you have to debug the telnet handshaking.

1
danidelvalle On

The issue, as "Stefano M" suggested, was related with the telnet session options negotiation. For some reason client and server were continuously exchanging options so select.select() never blocked (there were always data to be read).

I found a workaround by setting an option negotiation callback.

Telnet.set_option_negotiation_callback(callback)
Each time a telnet option is read on the input flow, this callback (if set) is called with the following parameters : callback(telnet socket, command (DO/DONT/WILL/WONT), option). No other action is done afterwards by telnetlib.