Troubleshooting Oserror: Out of Pty Devices

Close a PseudoTTY created via pty.openpty()

You can use os.close to close master and slave.

os.close(fd) Close file descriptor fd.

Note This function is intended for low-level I/O and must be applied
to a file descriptor as returned by os.open() or pipe(). To close a
“file object” returned by the built-in function open() or by popen()
or fdopen(), use its close() method.

OSError: [Errno 24] when multithreading pwntools

It turns out pwntools process API does not close stderr or stdout, so closing them before returning from run, solves the problem.

How to connect INET socket to PTY device in Python

This can be done using select.poll() instead of select.select(), because select.poll() will work with both File Descriptors and Sockets.

def sockToPty(clisock,addr):
(master, slave) = os.openpty()
tty.setraw(master, termios.TCSANOW)
print('PTY: Opened {} for {}'.format(os.ttyname(slave), addr))
mypoll = select.poll()
mypoll.register(clisock, select.POLLIN)
mypoll.register(master, select.POLLIN)
try:
while True:
fdlist = mypoll.poll(1000)
for fd,event in fdlist:
# We treat sockets and FDs differently
if fd == master:
data = os.read(fd, 4096)
if len(data) == 0:
print('PTY: {}, {} exiting due to Zero read.'.format(addr, os.ttyname(slave)))
raise GetOut
clisock.send(data)
else:
data = clisock.recv(4096)
if len(data) == 0:
print('PTY: {}, {} exiting due to Zero read.'.format(addr, os.ttyname(slave)))
raise GetOut
os.write(master, data)
except GetOut:
os.close(master)
os.close(slave)
clisock.shutdown(socket.SHUT_RDWR)
clisock.close()

This code is more complex than it needs to be for simple sockets - with a TCP socket, you can simply use the fileno() for that socket as a File Descriptor and then you treat both sides the same way (os.read(), os.write()). However, if you're going to use this with an SSLSocket, you need the more complicated version above, because if you grab the fileno() from an SSLSocket it expects you're going to handle the TLS layer as well as the data.

pty multiplexer

In the end I wrote a simple TCP server, just like I said I didn't want to... It works really well though. It uses the same general architecture as the code on the question but with TCP sockets instead of pseudo terminals.

I posted it here in case anyone wants to use it.

To call it:

md:mux_serial> ./mux_server.py --device /dev/ttyS0 --baud 115200 --port 23200
MUX > Serial port: /dev/ttyS0 @ 115200
MUX > Server: localhost:23200

I'm using socat on another terminal to access the port directly...

md:~> socat -,raw,echo=0,escape=0x0f TCP4:localhost:23200

...or to create a pseudo terminal to use inside scripts that require those:

md:~> socat -d -d pty,raw,echo=0 TCP4:localhost:23200
2012/10/01 13:08:21 socat[3798] N PTY is /dev/pts/4
2012/10/01 13:08:21 socat[3798] N opening connection to AF=2 127.0.0.1:23200
2012/10/01 13:08:21 socat[3798] N successfully connected from local address AF=2 127.0.0.1:35138
2012/10/01 13:08:21 socat[3798] N starting data transfer loop with FDs [3,3] and [5,5]


Related Topics



Leave a reply



Submit