Subject: kern/34129: Nonblocking write to pty returns 0, not EAGAIN
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Andreas Gustafsson <gson@gson.org>
List: netbsd-bugs
Date: 08/02/2006 18:30:00
>Number:         34129
>Category:       kern
>Synopsis:       Nonblocking write to pty can return 0
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Aug 02 18:30:00 +0000 2006
>Originator:     Andreas Gustafsson
>Release:        NetBSD 3.99.21
>Organization:
>Environment:
System: NetBSD guava.gson.org 3.99.21 NetBSD 3.99.21 (GENERIC) #1: Wed Jul 5 19:33:35 EEST 2006 gson@guru.araneus.fi:/usr/build/1002/obj/sys/arch/i386/compile/GENERIC i386
Architecture: i386
Machine: i386
>Description:

If a process is run under a pty in nonblocking mode, write() will
return 0 when the pty's buffer fills up.  This is incorrect; it should
return -1 and set errno to EAGAIN.

>How-To-Repeat:

I noticed the bug while attempting to remotely install NetBSD in a
headless virtual machine using qemu -nographic, boot-com1.fs, and an
ISO image.  Parts of the sysinst output would be lost, corrupting
the layout of some of the sysinst screens.

Since this is not trivial to repeat, here is a simpler test case:

Log in to a remote machine using ssh over a low-bandwidth connection
(1 Mbps or slower should suffice if the machine is fast enough).
Then compile and run the following test program:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv) {
        static char text[10];
        int i;
        fcntl(1, F_SETFL, O_NONBLOCK);
        for (i = 0; i < 100000; i++) {
                int r;
                sprintf(text, "%08d", i);
                text[8] = '\n';
                text[9] = '\0';         
                r = write(1, text, 9);
                if (r <= 0) {
                        sleep(2);
                        printf("write returned %d\n", r);
                        exit(1);
                }
        }
}

Notice how the program prints some number of lines of output and then
"write returned 0".  On other operating systems, it will correctly
print "write returned -1".

>Fix:

Not provided.