Subject: kern/2945: [dM] write() -> EINVAL not EPIPE
To: None <gnats-bugs@gnats.netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: netbsd-bugs
Date: 11/15/1996 21:37:08
>Number:         2945
>Category:       kern
>Synopsis:       [dM] write() -> EINVAL not EPIPE
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Nov 15 18:50:01 1996
>Last-Modified:
>Originator:     der Mouse
>Organization:
	Dis-
>Release:        1.2_BETA
>Environment:
	Found on NetBSD/sun3 somewhat-pre-1.2 -current (source tree sup
	date is July 3rd).
System: NetBSD Twig.Rodents.Montreal.QC.CA 1.2_BETA NetBSD 1.2_BETA (TWIG) #0: Tue Sep 3 00:45:26 EDT 1996 mouse@Twig.Rodents.Montreal.QC.CA:/mouse/sources/working-usr-src/sys/arch/sun3/compile/TWIG sun3

	Verified present on NetBSD/hp300, straight off the 1.2
	distribution tarballs.
System: NetBSD  1.2 NetBSD 1.2 (GENERIC) #7: Sun Sep 15 16:15:20 PDT 1996     thorpej@basalt:/u3/NetBSD-1.2/src/sys/arch/hp300/compile/GENERIC hp300

>Description:
	write() returns EINVAL in circumstances under which I believe
	it should be returning EPIPE.  Specifically:

	Server listen()s for connections
	Client connect()s
	Client blindly write()s data to the connection
	Server read()s one bufferful
	Server decides to dump the connection
	Server write()s a few bytes to the connection
	Server close()s the connection
	Client's write gets EINVAL instead of the expected EPIPE
>How-To-Repeat:

Note that the "parent write error" printed is "Invalid argument",
rather than the expected "Broken pipe".

[Twig] 1> cat writebug.c
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <strings.h>
#include <sys/socket.h>
#include <netinet/in.h>

char **argvec;

#define CHK(call) chk((call),#call)

static int chk(int value, const char *txt)
{
 if (value < 0)
  { fprintf(stderr,"%s: %s: %s\n",argvec[0],txt,strerror(errno));
    exit(1);
  }
 return(value);
}

static void child(int fd)
{
 char buf[10240];
 int n;

 fprintf(stderr,"%s: child calling read()\n",argvec[0]);
 n = read(fd,&buf[0],sizeof(buf));
 fprintf(stderr,"%s: child read returned %d\n",argvec[0],n);
 fprintf(stderr,"%s: child calling write()\n",argvec[0]);
 n = write(fd,"this is a message\n",18);
 fprintf(stderr,"%s: child write returned %d\n",argvec[0],n);
 close(fd);
 sleep(10);
}

static void parent(int fd)
{
 int n;
 char buf[4096];

 sleep(1); /* let child block in read() */
 bzero(&buf[0],sizeof(buf));
 while (1)
  { fprintf(stderr,"%s: parent calling write()\n",argvec[0]);
    n = write(fd,&buf[0],sizeof(buf));
    if (n < 0)
     { fprintf(stderr,"%s: parent write error: %s\n",argvec[0],strerror(errno));
       exit(1);
     }
    else
     { fprintf(stderr,"%s: parent write returned %d\n",argvec[0],n);
     }
  }
}

int main(int, char **);
int main(int ac __attribute__ ((unused)), char **av)
{
 int s;
 struct sockaddr_in sin;
 int sinlen;
 int pid;

 argvec = av;
 signal(SIGPIPE,SIG_IGN);
 s = CHK(socket(AF_INET,SOCK_STREAM,0));
 bzero(&sin,sizeof(sin));
 sin.sin_family = AF_INET;
 sin.sin_addr.s_addr = INADDR_ANY;
 sin.sin_port = 0;
 CHK(bind(s,(struct sockaddr *)&sin,sizeof(sin)));
 sinlen = sizeof(sin);
 CHK(getsockname(s,(struct sockaddr *)&sin,&sinlen));
 CHK(listen(s,3));
 pid = CHK(fork());
 if (pid == 0)
  { close(s);
    s = CHK(socket(AF_INET,SOCK_STREAM,0));
    CHK(connect(s,(struct sockaddr *)&sin,sizeof(sin)));
    child(s);
  }
 else
  { sinlen = sizeof(sin);
    s = CHK(accept(s,(struct sockaddr *)&sin,&sinlen));
    parent(s);
  }
 exit(0);
}
[Twig] 2> cc -o writebug writebug.c
[Twig] 3> ktrace -i ./writebug
./writebug: child calling read()
./writebug: parent calling write()
./writebug: child read returned 2048
./writebug: child calling write()
./writebug: child write returned 18
./writebug: parent write returned 4096
./writebug: parent calling write()
./writebug: parent write error: Invalid argument
[Twig] 4> kdump
 29314 ktrace   RET   ktrace 0
 29314 ktrace   CALL  execve(0xdfffa9e,0xdfffa30,0xdfffa38)
 29314 ktrace   NAMI  "./writebug"
 29314 writebug EMUL  "netbsd"
 29314 writebug RET   execve 0
 29314 writebug CALL  open(0x20b8,0,0)
 29314 writebug NAMI  "/usr/libexec/ld.so"
 29314 writebug RET   open 3
 29314 writebug CALL  read(0x3,0xdfff9f8,0x20)
 29314 writebug GIO   fd 3 read 32 bytes
       "\M-@\M^G\^A\v\0\0\240\0\0\0 \0\0\0\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0\0"
 29314 writebug RET   read 32/0x20
 29314 writebug CALL  mmap(0,0xc000,0x5,0x4,0x3,0,0,0)
 29314 writebug RET   mmap 67239936/0x4020000
 29314 writebug CALL  mmap(0x402a000,0x2000,0x3,0x14,0x3,0,0,0xa000)
 29314 writebug RET   mmap 67280896/0x402a000
 29314 writebug CALL  getuid
 29314 writebug RET   getuid 999/0x3e7
 29314 writebug CALL  geteuid
 29314 writebug RET   geteuid 999/0x3e7
 29314 writebug CALL  getgid
 29314 writebug RET   getgid 0
 29314 writebug CALL  getegid
 29314 writebug RET   getegid 0
 29314 writebug CALL  __sysctl(0xdfff91c,0x2,0x402ba8c,0xdfff924,0,0)
 29314 writebug RET   __sysctl 0
 29314 writebug CALL  mmap(0,0x8000,0x3,0x1004,0xffffffff,0,0,0)
 29314 writebug RET   mmap 67371008/0x4040000
 29314 writebug CALL  mmap(0,0xa000,0x3,0x1004,0xffffffff,0,0,0)
 29314 writebug RET   mmap 67502080/0x4060000
 29314 writebug CALL  open(0x402153a,0,0)
 29314 writebug NAMI  "/var/run/ld.so.hints"
 29314 writebug RET   open 4
 29314 writebug CALL  mmap(0,0x2000,0x1,0x4,0x4,0,0,0)
 29314 writebug RET   mmap 67633152/0x4080000
 29314 writebug CALL  open(0x4080322,0,0)
 29314 writebug NAMI  "/usr/lib/libc.so.12.5"
 29314 writebug RET   open 5
 29314 writebug CALL  read(0x5,0xdfff94c,0x20)
 29314 writebug GIO   fd 5 read 32 bytes
       "\M-@\M^G\^A\v\0\^D\M-@\0\0\0\M^@\0\0\0\M^G$\0\0001\M-`\0\0\0 \0\0\0\0\
        \0\0\0\0"
 29314 writebug RET   read 32/0x20
 29314 writebug CALL  mmap(0,0x5c724,0x5,0x4,0x5,0,0,0)
 29314 writebug RET   mmap 67764224/0x40a0000
 29314 writebug CALL  mprotect(0x40ec000,0x8000,0x7)
 29314 writebug RET   mprotect 0
 29314 writebug CALL  mmap(0x40f4000,0x8724,0x7,0x1014,0xffffffff,0,0,0)
 29314 writebug RET   mmap 68108288/0x40f4000
 29314 writebug CALL  close(0x5)
 29314 writebug RET   close 0
 29314 writebug CALL  munmap(0x4080000,0x2000)
 29314 writebug RET   munmap 0
 29314 writebug CALL  close(0x4)
 29314 writebug RET   close 0
 29314 writebug CALL  close(0x3)
 29314 writebug RET   close 0
 29314 writebug CALL  sigaction(0xd,0xdfff9d8,0xdfff9cc)
 29314 writebug RET   sigaction 0
 29314 writebug CALL  socket(0x2,0x1,0)
 29314 writebug RET   socket 3
 29314 writebug CALL  bind(0x3,0xdfff9fc,0x10)
 29314 writebug RET   bind 0
 29314 writebug CALL  getsockname(0x3,0xdfff9fc,0xdfff9f8)
 29314 writebug RET   getsockname 0
 29314 writebug CALL  listen(0x3,0x3)
 29314 writebug RET   listen 0
 29314 writebug CALL  fork
 29314 writebug RET   fork 29315/0x7283
 29314 writebug CALL  accept(0x3,0xdfff9fc,0xdfff9f8)
 29315 writebug RET   fork 0
 29315 writebug CALL  close(0x3)
 29315 writebug RET   close 0
 29315 writebug CALL  socket(0x2,0x1,0)
 29315 writebug RET   socket 3
 29315 writebug CALL  connect(0x3,0xdfff9fc,0x10)
 29314 writebug RET   accept 4
 29314 writebug CALL  sigprocmask(0x1,0x2000)
 29314 writebug RET   sigprocmask 0
 29314 writebug CALL  sigaction(0xe,0xdffe9ac,0xdffe9a0)
 29314 writebug RET   sigaction 0
 29314 writebug CALL  setitimer(0,0xdffe9c8,0xdffe9b8)
 29314 writebug RET   setitimer 0
 29314 writebug CALL  sigsuspend(0)
 29315 writebug RET   connect 0
 29315 writebug CALL  write(0x2,0xdffcb28,0x21)
 29315 writebug GIO   fd 2 wrote 33 bytes
       "./writebug: child calling read()
       "
 29315 writebug RET   write 33/0x21
 29315 writebug CALL  read(0x3,0xdffd1e8,0x2800)
 29314 writebug PSIG  SIGALRM caught handler=0x40c0226 mask=0x2000 code=0x0
 29314 writebug RET   sigsuspend -1 errno 4 Interrupted system call
 29314 writebug CALL  sigreturn(0xdffe954)
 29314 writebug RET   sigreturn JUSTRETURN
 29314 writebug CALL  sigprocmask(0x3,0)
 29314 writebug RET   sigprocmask 8192/0x2000
 29314 writebug CALL  sigaction(0xe,0xdffe9a0,0)
 29314 writebug RET   sigaction 0
 29314 writebug CALL  setitimer(0,0xdffe9b8,0xdffe9c8)
 29314 writebug RET   setitimer 0
 29314 writebug CALL  write(0x2,0xdffe328,0x23)
 29314 writebug GIO   fd 2 wrote 35 bytes
       "./writebug: parent calling write()
       "
 29314 writebug RET   write 35/0x23
 29314 writebug CALL  write(0x4,0xdffe9e4,0x1000)
 29314 writebug GIO   fd 4 wrote 4096 bytes
[4096 \0s deleted]
 29315 writebug GIO   fd 3 read 2048 bytes
[2048 \0s deleted]
 29315 writebug RET   read 2048/0x800
 29315 writebug CALL  write(0x2,0xdffcb24,0x25)
 29315 writebug GIO   fd 2 wrote 37 bytes
       "./writebug: child read returned 2048
       "
 29315 writebug RET   write 37/0x25
 29315 writebug CALL  write(0x2,0xdffcb28,0x22)
 29315 writebug GIO   fd 2 wrote 34 bytes
       "./writebug: child calling write()
       "
 29315 writebug RET   write 34/0x22
 29315 writebug CALL  write(0x3,0x2803,0x12)
 29315 writebug GIO   fd 3 wrote 18 bytes
       "this is a message
       "
 29315 writebug RET   write 18/0x12
 29315 writebug CALL  write(0x2,0xdffcb24,0x24)
 29315 writebug GIO   fd 2 wrote 36 bytes
       "./writebug: child write returned 18
       "
 29315 writebug RET   write 36/0x24
 29315 writebug CALL  close(0x3)
 29315 writebug RET   close 0
 29315 writebug CALL  sigprocmask(0x1,0x2000)
 29315 writebug RET   sigprocmask 0
 29315 writebug CALL  sigaction(0xe,0xdffd1ac,0xdffd1a0)
 29315 writebug RET   sigaction 0
 29315 writebug CALL  setitimer(0,0xdffd1c8,0xdffd1b8)
 29315 writebug RET   setitimer 0
 29315 writebug CALL  sigsuspend(0)
 29314 writebug RET   write 4096/0x1000
 29314 writebug CALL  write(0x2,0xdffe324,0x27)
 29314 writebug GIO   fd 2 wrote 39 bytes
       "./writebug: parent write returned 4096
       "
 29314 writebug RET   write 39/0x27
 29314 writebug CALL  write(0x2,0xdffe328,0x23)
 29314 writebug GIO   fd 2 wrote 35 bytes
       "./writebug: parent calling write()
       "
 29314 writebug RET   write 35/0x23
 29314 writebug CALL  write(0x4,0xdffe9e4,0x1000)
 29314 writebug RET   write -1 errno 22 Invalid argument
 29314 writebug CALL  open(0xdffe5a4,0,0x40c9ec7)
 29314 writebug NAMI  "/usr/share/nls/C/libc.cat"
 29314 writebug RET   open 5
 29314 writebug CALL  fstat(0x5,0xdffe528)
 29314 writebug RET   fstat 0
 29314 writebug CALL  mmap(0,0xe5a,0x1,0x1,0x5,0,0,0)
 29314 writebug RET   mmap 67633152/0x4080000
 29314 writebug CALL  close(0x5)
 29314 writebug RET   close 0
 29314 writebug CALL  __sysctl(0xdffe4e0,0x2,0x40fc720,0xdffe4e8,0,0)
 29314 writebug RET   __sysctl 0
 29314 writebug CALL  break(0x426c)
 29314 writebug RET   break 0
 29314 writebug CALL  break(0x5ffc)
 29314 writebug RET   break 0
 29314 writebug CALL  break(0x7ffc)
 29314 writebug RET   break 0
 29314 writebug CALL  munmap(0x4080000,0xe5a)
 29314 writebug RET   munmap 0
 29314 writebug CALL  write(0x2,0xdffe324,0x31)
 29314 writebug GIO   fd 2 wrote 49 bytes
       "./writebug: parent write error: Invalid argument
       "
 29314 writebug RET   write 49/0x31
 29314 writebug CALL  exit(0x1)
[Twig] 5> 

>Fix:
	Darned if I know.  At present I have no idea why it's happening
	to begin with.

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     01 EE 31 F6 BB 0C 34 36  00 F3 7C 5A C1 A0 67 1D
>Audit-Trail:
>Unformatted: