I've encountered characters being lost while writing large buffers to a
pseudoterminal master on OpenBSD 5.2.  The linked program ptycheck.c
exercises this behavior on 5.2 i386/amd64 (as well as 4.7 and 4.8 i386):

https://gist.github.com/4377173

Briefly, the program opens a pty pair and generates a pseudorandom
message of MESSAGE_LEN bytes.  It then forks off a child process which
writes this message to the master; meanwhile, the parent process
attempts to read this message back through the slave.  On OpenBSD 5.2,
however, the parent blocks indefinitely after reading only 4088 out of
4096 expected bytes from the pty slave.  Similar behavior is observed
with other values of MESSAGE_LEN >= 1024.

This seems to be a small issue with ptcwrite in sys/kern/tty_pty.c.
When tp->t_rawq hits 1022 bytes awaiting read from the pty slave,
control will jump to the "block" label from line 573.  But in the case
that uio->uio_resid is zero (all characters have been copied from uio to
the 100-byte kernel space buf on ptcwrite's stack) but cc > 0 (more
characters in buf still need to be sent), control will not reenter the

    while (uio->uio_resid > 0) {
            /* ... */
    }

loop upon jumping to "again" after tsleep, and these remaining
characters are lost.  i.e., up to BUFSIZ == 100 characters can be
discarded when performing writes of greater than 1022 bytes.

The following patch alters the loop condition so that ptycheck.c no
longer fails...

Mark


Index: sys/kern/tty_pty.c
===================================================================
RCS file: /cvs/src/sys/kern/tty_pty.c,v
retrieving revision 1.58
diff -u sys/kern/tty_pty.c
--- sys/kern/tty_pty.c  22 Apr 2012 05:43:14 -0000      1.58
+++ sys/kern/tty_pty.c  25 Dec 2012 18:06:42 -0000
@@ -550,7 +550,7 @@
                wakeup(&tp->t_canq);
                goto done;
        }
-       while (uio->uio_resid > 0) {
+       while (uio->uio_resid > 0 || cc > 0) {
                if (cc == 0) {
                        cc = MIN(uio->uio_resid, BUFSIZ);
                        if (cc > bufcc)

Reply via email to