Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Dec 2006 16:07:09 +0100 (CET)
From:      "Arne H. Juul" <arnej@pvv.ntnu.no>
To:        freebsd-java@FreeBSD.org
Cc:        freebsd-threads@freebsd.org
Subject:   Re: close() of active socket does not work on FreeBSD 6
Message-ID:  <Pine.LNX.4.62.0612111552480.16908@decibel.pvv.ntnu.no>
In-Reply-To: <Pine.LNX.4.62.0612111535280.32258@decibel.pvv.ntnu.no>
References:  <Pine.LNX.4.62.0612111535280.32258@decibel.pvv.ntnu.no>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 11 Dec 2006, Arne H. Juul wrote:
> I've had problems with some tests hanging on FreeBSD 6/amd64. This happens
> both with diablo-1.5.0_07-b01 and the java/jdk15 compiled from ports.
>
> After much digging we've determined that the root cause is that
> the guarantee in the socket.close() API, see the documentation at
> http://java.sun.com/j2se/1.5.0/docs/api/java/net/Socket.html#close()
> isn't fulfulled - the thread blocked in I/O on the socket doesn't wake up.

Looking at the Java VM source code it does some tricks with dup2() to 
reopen the close()'d filedescriptor, making it point to a filedescriptor 
that's pre-connected to a closed socket.

A small C program that duplicates this (using pipes to make it a bit
simpler) follows.  I'm not sure if any standards demand that this
works like it used to on FreeBSD 4 / libc_r, but since Java uses it it
would be really nice if this could be made to work in FreeBSD 6 (libthr
and libpthread).   Or maybe somebody has another suggestions on how to
implement the Java close() semantics?

Anyway, the following C program works as intended on FreeBSD 4,
hangs on FreeBSD 6 (amd64), compiled with:
 	 cc -Wall -pthread read_dup2.c -o read_dup2


#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

int p[2];

void *run(void *arg) {
   ssize_t res;
   char tmp[128];
   fprintf(stderr, "reading...\n");
   res = read(p[0], tmp, sizeof(tmp));
   fprintf(stderr, "read result: %d\n", (int)res);
   if (res < 0) {
     perror("read");
   }
   return arg;
}

int main(int argc, char **argv) {
   pthread_t t;
   int d = open("/dev/null", O_RDONLY);
   if (pipe(p) != 0) {
     perror("pipe");
     return 1;
   }
   if (pthread_create(&t, NULL, run, NULL) != 0) {
     perror("thread create");
     return 1;
   }
   sleep(1);
   d = open("/dev/null", O_RDONLY);
   if (d < 0) {
     perror("open dev null");
     exit(1);
   }
   if (dup2(d, p[0]) < 0) {
     perror("dup2");
     exit(1);
   }
   if (pthread_join(t, NULL) != 0) {
     perror("thread join");
     exit(1);
   }
   return 0;
}



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