The following code prints nothing, but it should print out "a" repeatedly. The forked process blocks on the os.read(0, 1). The parent process is indeed writing to the stdin_master, but stdin_slave receives nothing. Any ideas?
import os
import pty
import resource
import select
import signal
import time
stdin_master, stdin_slave = pty.openpty()
stdout_master, stdout_slave = pty.openpty()
stderr_master, stderr_slave = pty.openpty()
pid = os.fork()
# child process
if pid == 0:
os.setsid()
os.close(stdin_master)
os.close(stdout_master)
os.close(stderr_master)
os.dup2(stdin_slave, 0)
os.dup2(stdout_slave, 1)
os.dup2(stderr_slave, 2)
max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
os.closerange(3, max_fd)
while True:
char = os.read(0, 1)
os.write(1, char)
os._exit(255)
# parent process
else:
os.close(stdin_slave)
os.close(stdout_slave)
os.close(stderr_slave)
try:
while True:
read, write, err = select.select([stdout_master], [stdin_master], [], 0)
for to_read in read:
print os.read(to_read, 1)
for to_write in write:
os.write(to_write, "a")
time.sleep(0.1)
finally:
os.kill(pid, signal.SIGKILL)
Thomas Wouters was kind enough to furnish the answer:
PTYs can only be read from the master fd. So the child's os.read(0, 1) was not working because of this. If we change
to
Now the chlid will be reading from the master, and we'll be writing to the slave from the parent. This works.
I'm not sure your want to be using the
pty
module here. What you seem to need is basically a pair ofos.pipe
's.Here's a solution that works using pipes: