I wrote and maintain a program rlwrap that uses a pseudo-terminal to communicate with a child process. Pseudo-terminals (ptys) are found in all Unix(-like) systems, but they behave slightly differently on different platforms.
Case in point: In rlwrap
, the parent process keeps the slave pty open to keep tabs on the child's terminal settings (on Linux and FreeBSD one can use the master for that, but not in Solaris, for example)
On FreeBSD (8.2) (but not Linux) this leads to the loss of the child's final output. For example:
#include <stdio.h> /* save as test.c and compile with gcc -o test test.c -lutil */ #define BUFSIZE 255 int main(void) { int master, slave; char buf[BUFSIZE]; int nread; openpty(&master, &slave, NULL, NULL, NULL); if (fork()) { /* parent: */ close(slave); /* leave this out and lose slave's final words ... WHY? */ do { nread = read(master, buf, BUFSIZE); write(STDOUT_FILENO, buf, nread); /* echo child's output to stdout */ } while (nread > 0); } else { /* child: */ login_tty(slave); /* this makes child a session leader and slave a controlling */ /* terminal for it, then dup()s std{in,out,err} to slave */ printf("Feeling OK :-)\n"); sleep(1); printf("Feeling unwell ... Arghhh!\n"); /* this line may get lost */ } return 0; }
The parent process will echo the child's output, as expected, but when I omit the close(slave)
(keeping it open like in rlwrap
):
Is this behaviour documented somewhere? Is there a rationale for it? Can I circumvent it without closing the slave in the parent process?
I found out that not making the slave a controlling terminal - replacing the login_tty
call with a few simple dup()
calls - will cure the problem. This is no solution for rlwrap
however: quite a few commands need a controlling terminal (/dev/tty
) to talk to, so rlwrap
has to provide one for them.
I think there is unique separate behaviour for the Pty.
The code relies on the pipe existing long enough to send the data through, but the child exiting may cause the virtual channel to be deleted before the data is received.
This would be unique to Pty, and not exist for real terminal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With