read hang on datagram socket

Kurt Miller lists at intricatesoftware.com
Thu Jan 26 15:26:30 PST 2006


I'm working on 1.5 jdk certification on 5.4 and 6.0. One of the jck
tests hangs on 5.4 but works ok on 6.0. I've reduced the problem
down to the following C program that hangs on 5.4 but works fine
(finishes) on 6.0 and 4.11.

I could use some assistance with finding a work-around to the
problem or an explanation as to why the program hangs on 5.4.

Thank you,
-Kurt

#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <netinet/in.h>

void
buildAddr4(struct sockaddr_in *addr4, int address, short port) {
  memset((char *) addr4, 0, sizeof(struct sockaddr_in));
  addr4->sin_port = htons(port);
  addr4->sin_addr.s_addr = (uint32_t) htonl(address);
  addr4->sin_family = AF_INET;
}

void
setAddress(struct sockaddr_in *addr4, int address) {
  addr4->sin_addr.s_addr = (uint32_t) htonl(address);
}

int
getHostAddress() {
  char hostname[MAXHOSTNAMELEN];
  struct addrinfo  hints, *res;
  int address = 0;

  if (gethostname(hostname, MAXHOSTNAMELEN) != 0)
    exit(1);

  memset(&hints, 0, sizeof(hints));
  hints.ai_flags = AI_CANONNAME;
  hints.ai_family = AF_INET;

  if(getaddrinfo(hostname, "domain", &hints, &res) != 0)
    exit(1);

  while( res != NULL ) {
    if (res->ai_family == AF_INET) {
      address = ntohl(((struct sockaddr_in*)(res->ai_addr))->sin_addr.s_addr);
      break;
    }
    res = res->ai_next;
  }

  return address;
}

int
main() {
  int sock1, sock2;
  int optval = 1;
  struct sockaddr addr;
  struct sockaddr sock1Addr, sock2Addr;
  int sock1AddrLen, sock2AddrLen;
  short port1, port2;
  char sendBuf, readBuf;
  int hostAddress;

  if ((hostAddress = getHostAddress()) == 0)
    exit(1);

  buildAddr4((struct sockaddr_in *)&addr, 0, 0);

  if ((sock1 = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    exit(1);
  if (setsockopt(sock1, SOL_SOCKET, SO_BROADCAST, (char*) &optval, sizeof(optval)) != 0)
    exit(1);
  if (bind(sock1, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0)
    exit(1);
  if (getsockname(sock1, &sock1Addr, &sock1AddrLen) != 0)
    exit(1);
  setAddress((struct sockaddr_in *)&sock1Addr, hostAddress);

  if ((sock2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    exit(1);
  if (bind(sock2, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) != 0)
    exit(1);
  if (getsockname(sock2, &sock2Addr, &sock2AddrLen) != 0)
    exit(1);
  setAddress((struct sockaddr_in *)&sock2Addr, hostAddress);
  if (connect(sock2, &sock1Addr, sock1AddrLen) != 0)
    exit(1);

  sendBuf = 22;
  if (sendto(sock1, &sendBuf, 1, 0, &sock2Addr, sock2AddrLen) != 1)
    exit(1);

  if (read(sock2, &readBuf, 1) != 1)
    exit(1);

  printf("no hang\n");
}


More information about the freebsd-hackers mailing list