From loschert@dev.accucount.com  Fri Sep 18 13:43:45 1998
Received: from dev.accucount.com (dev.accucount.com [209.50.225.32])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id NAA29584;
          Fri, 18 Sep 1998 13:43:20 -0700 (PDT)
          (envelope-from loschert@dev.accucount.com)
Received: (from loschert@localhost)
	by dev.accucount.com (8.8.8/8.8.8) id QAA26921;
	Fri, 18 Sep 1998 16:41:42 GMT
	(envelope-from loschert)
Message-Id: <199809181641.QAA26921@dev.accucount.com>
Date: Fri, 18 Sep 1998 16:41:42 GMT
From: loschert@servint.com
Reply-To: loschert@servint.com
To: FreeBSD-gnats-submit@freebsd.org, freebsd-stable@freebsd.org
Subject: SIGPIPE and write() errors with -libc_r
X-Send-Pr-Version: 3.2

>Number:         7981
>Category:       misc
>Synopsis:       SIGPIPE & write() errors with -libc_r
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          doc-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 18 13:50:02 PDT 1998
>Closed-Date:    Thu Dec 10 15:57:41 PST 1998
>Last-Modified:  Thu Dec 10 15:58:36 PST 1998
>Originator:     Matt Loschert
>Release:        FreeBSD 2.2.7-STABLE i386
>Organization:
ServInt Internet Services
>Environment:

	FreeBSD 2.2.7-STABLE (last make world about 3 weeks ago)

>Description:

	When linking the thread-safe c library (-libc_r), write()
	calls do NOT return -1 and set errno to EPIPE, after writing
	to a closed socket.  Also, once the write takes place on the
	closed socket, the offending process receives a continuous
	series of SIGPIPE signals from the system.

>How-To-Repeat:

	Compile the following file with the command:

	--> 	gcc -O2 -Wall -o srv srv.c -lc_r

	Run the program in the background:

	-->	./srv &

	Telnet to srv:

	-->	telnet 0 9999

	Type some characters, then quickly issue the telnet disconnect
	command (Ctrl-} q).

	If the disconnect command is received prior to the server's
	response (the server waits 2 seconds), the server will attempt
	to write to a now-disconnected socket.  When this happens, the
	process should receive tons of SIGPIPE's.

	Note: This code was adapted from code by John Shapely Gray on
	page 297 of his book 'Interprocess Communications in Unix: The
	Nooks & Crannies'.

------------------->cut here<------------------------

/*
 * filename: srv.c
 */

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 9999

static char  buf[BUFSIZ];
int          sig = 0;
extern int   errno;

void   sig_catch(int);
void  *client_handler(void *arg);


int main(void) 
{
     int         serverSkt,
                *clientSkt,
                 clientlength;
     struct sockaddr_in
                 client_address,
                 server_address;
     pthread_t  *client_thread;

     signal(SIGPIPE, sig_catch);
     
     if((serverSkt=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
          perror("Generate error");
          exit(1);
     }

     bzero(&server_address, sizeof(server_address));
     server_address.sin_family      = AF_INET;
     server_address.sin_addr.s_addr = htonl(INADDR_ANY);
     server_address.sin_port        = htons(PORT);
     
     if((bind(serverSkt, (struct sockaddr *) &server_address,
              sizeof(server_address))) == -1)
     {
          perror("bind error");
          close(serverSkt);
          exit(2);
     }

     if(listen(serverSkt, 5) < 0) {
          perror("listen error");
          exit(3);
     }


     for(;;) {
          clientlength = sizeof(client_address);
          
          if((clientSkt = (int *) malloc (sizeof(int))) == NULL) {
               perror("malloc error");
               exit(4);
          }

          if((*clientSkt = accept(serverSkt, (struct sockaddr *) &client_address,
                                &clientlength)) == -1)
          {
               perror("accept error");
               exit(5);
          }


          if((client_thread = (pthread_t *) malloc (sizeof(pthread_t))) == NULL) {
               perror("malloc error");
               exit(6);
          }
               
          if(pthread_create(client_thread, NULL, &client_handler, clientSkt)) {
               perror("pthread_create error");
               exit(7);
          }

          if(pthread_detach(*client_thread)) {
               perror("pthread_detach error");
               exit(8);
          }

          free(client_thread);
     }
     exit(0);
}




void *client_handler(void *arg)
{
     int  wlen, len, i, skt;

     skt = *((int *) arg);
     free(arg);

     while((len = read(skt, buf, BUFSIZ)) > 0) {
          sleep(2);
          for(i = 0; i < len; i++)
               buf[i] = toupper(buf[i]);
          if((wlen = write(skt, buf, len)) <= 0) {
               perror("Write failed");
               close(skt);
               exit(5);
          }
          printf( "Write(1) len = %d\n", wlen);
          
          if((wlen = write(skt, "", sizeof(""))) <= 0) {
               printf("wlen=%d\n", wlen);
               perror("Write failed");
               close(skt);
               exit(5);
          }
          
          printf( "Write(2) len = %d\n", wlen);
          if (buf[0] == '.') break;
     }    
     close(skt);
     exit(0);
}

void sig_catch(int s) {
     printf ("Signal %d detected\n", s);
}



------------------->cut here<------------------------

>Fix:
	
	Don't know.

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: steve 
State-Changed-When: Thu Dec 10 15:57:41 PST 1998 
State-Changed-Why:  
Confirmed fixed in 2.2.8-RELEASE by originator.  Thanks for the 
quick reply, Matt. 
>Unformatted:
