Mail Archives: cygwin-developers/1998/02/02/09:50:32
From: Sergey Okhapkin <sos AT prospect DOT com DOT ru>
Date: Mon, 2 Feb 1998 17:16:34 +0300
Thu Jan 22 18:46:40 1998 Ian Lance Taylor <ian AT cygnus DOT com>
* tty.h (class tty): Change slave_handles to int.
* tty.cc (fhandler_tty_slave::open): Check for invalid tty
handles. If this is the first slave, set slave_handles to 2;
otherwise, increment slave_handles.
(fhandler_tty_slave::close): Only close the tty handles if the
slave_handles field drops to 1.
This changes fools rxvt. Rxvt does the following:
pty = open("/dev/ptmx");
slave = ptsname(pty);
lstat(slave);
tty = open(slave);
Lstat call implemented in cygwin as fd=open(name); fstat(fd); close(fd).
This close call closes input_handle and output_handle in tty structure
(because number of slaves drops to 1) and tty=open(slave) call fails. Ian,
any ideas to fix it?
The basic problem with implementing ptys on top of pipes is getting
the handles closed appropriately. To make expect work, I needed the
master pty to correctly detect EOF when the slave pty was closed. The
slave was open in a child process, and the master was sleeping in the
read system call. To make this work, I made opening a slave copy the
handles into the process opening the slave. This is done in
fhandler_tty_slave::open.
Of course, it follows that closing the slave must close the handles,
which happens in fhandler_tty_slave::close when all the slaves are
closed.
Unfortunately, this does not handle the case of the master opening the
pty, then a child opening the pty, and then closing the pty, and then
another child opening the pty. This works on Unix, but I do not know
how to make it work on Windows. I don't happen to know of any
programs that rely on this behaviour, but there may be some.
You are running into this problem, because lstat does an open behind
the scenes. I can think of a couple of ways to fix this particular
instance of the problem.
1) Change stat and lstat to not actually call open on the file. Doing
that seems moderately bogus anyhow. You should be able to call stat
without running out of file descriptors. It does seem that for some
reason Windows before NT 4.0 forces you to call OpenFile, but that
does not need to imply open.
2) Have the fhandler_tty_save::open check whether the master and the
slave are the same process. In this case, there is no need to
duplicate the tty handles at all. We would have to record this in
some other way in the tty structure, perhaps by adding a flag field of
some sort. This needs to be handled correctly when doing a fork
tricky. If the slave is closed in the parent, we will need to hand
off the descriptors to the child in order to make read detect EOF
correctly. However, if the slave is not closed, we do not want to
hand off the descriptors. So the handoff would need to happen when
the slave is closed. This is basically a matter of updating the tty
structure information when the slave is closed in the parent. The pty
code is full of race conditions at present, and this would
unfortunately be another one. This would not solve the general
problem of reopening a slave pty, but it would solve the particular
case you are running into.
Does anybody have any other thoughts?
Ian
- Raw text -