[omniORB] Help to verify the behaviour of shutdown() socket call

Sai-Lai Lo S.Lo@uk.research.att.com
17 Sep 1999 11:59:05 +0100


It seems that the shutdown() socket call on HPUX 11.00 behaves differently
from other implementations.

In the ORB, we call shutdown() from one thread while another thread is
blocking on recv() on the same socket. On all the platforms we use here,
the behaviour is that the kernel would kick the thread blocking on recv()
out of the system call. It seems that HPUX 11.00 does not do that and the
thread continues to block on recv().

Does anyone who knows about HPUX can comment on this issue? Is there some
-D flags we can set to get the usual behaviour?

Here is a short C program to illustrate the problem.

To use the test:

1. Compile the program, it uses pthread so add the necessary compiler flag.
2. run testshutdown on machine foo. Note the port number in the output. 
3  telnet foo <port number>

The output from testshutdown should look like this:

$ ./testshutdown
Listen on port number: 3794
Got a new connection
Silly: block on recv 4.
shutdown connection 4              <---- After 10 seconds
Silly: close connection 4.

And the telnet session said close foreign host.

It seems that "Silly" on HPUX 11.00 never returns from recv().
But what about HPUX 10.20?

Sai-Lai

---------------------------------------
/* testshutdown.c */
#include <pthread.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>

#if (defined(__GLIBC__) && __GLIBC__ >= 2)
#  define SOCKLEN_T  socklen_t
#elif defined(__aix__) || defined(__VMS) || defined(__SINIX__)
#  define SOCKLEN_T  size_t
#else
#  define SOCKLEN_T  int
#endif

void*
silly(void* arg)
{
  int fd = (int) arg;
  void* buf;
  int len;

  buf = (void*)malloc(10);
  len = 10;

  fprintf(stderr,"Silly: block on recv %d.\n",fd);
  while (1) {
    if (recv(fd,(char*)buf,len,0) <= 0) {
      fprintf(stderr,"Silly: close connection %d.\n",fd);
      close(fd);
      return 0;
    }
  }
}


int
main(int argc, char** argv)
{
  struct sockaddr_in myaddr,raddr;
  int sock;
  int newsock;
  SOCKLEN_T l;
  pthread_t worker;
  
  sock = socket(AF_INET,SOCK_STREAM,0);
  myaddr.sin_family = AF_INET;
  myaddr.sin_addr.s_addr = INADDR_ANY;
  myaddr.sin_port = 0;

  if (bind(sock,(struct sockaddr *)&myaddr,sizeof(struct sockaddr_in))) {
    fprintf(stderr,"Cannot bind to socket\n");
    close(sock);
    return 1;
  }

  if (listen(sock,5)) {
    fprintf(stderr,"Cannot listen to socket\n");
    close(sock);
    return 1;
  }

  l = sizeof(struct sockaddr_in);
  if (getsockname(sock,(struct sockaddr *)&myaddr,&l)) {
    fprintf(stderr,"Cannot get sockname\n");
    close(sock);
    return 1;
  }

  fprintf(stderr,"Listen on port number: %d\n",ntohs(myaddr.sin_port));

  while (1) {

    newsock = accept(sock,(struct sockaddr *)&raddr,&l);

    fprintf(stderr,"Got a new connection\n");

    pthread_create(&worker,NULL,silly,(void*)newsock);

    sleep(10);
    shutdown(newsock,2);
    fprintf(stderr,"shutdown connection %d\n",newsock);
  }


  return 0;
}
-------------------------------




-- 
Sai-Lai Lo                                   S.Lo@uk.research.att.com
AT&T Laboratories Cambridge           WWW:   http://www.uk.research.att.com 
24a Trumpington Street                Tel:   +44 1223 343000
Cambridge CB2 1QA                     Fax:   +44 1223 313542
ENGLAND