Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Sep 1998 16:41:42 GMT
From:      loschert@servint.com
To:        FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-stable@FreeBSD.ORG
Subject:   SIGPIPE and write() errors with -libc_r
Message-ID:  <199809181641.QAA26921@dev.accucount.com>

next in thread | raw e-mail | index | archive | help

>Submitter-Id:   current-users
>Originator:     Matt Loschert
>Organization:   ServInt Internet Services
>Confidential:   no
>Synopsis:       SIGPIPE & write() errors with -libc_r
>Severity:       serious
>Priority:       high
>Category:       misc
>Release:        FreeBSD 2.2.7-STABLE i386
>Class:          doc-bug
>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.


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199809181641.QAA26921>