Re: close() of active socket does not work on FreeBSD 6
- From: Kostik Belousov <kostikbel@xxxxxxxxx>
- Date: Mon, 11 Dec 2006 19:11:15 +0200
On Mon, Dec 11, 2006 at 04:07:09PM +0100, Arne H. Juul wrote:
On Mon, 11 Dec 2006, Arne H. Juul wrote:
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;
}
I think that -arch@ is proper ML to discuss the issue.
Your test example hangs becase read() takes one more hold count on the
file descriptor operated upon. As result, when calling close, f_count
of the rpipe (aka p[0]) is 2, close() decrements it, f_count becomes
1. Since f_count > 0, fdrop_locked simply returns instead of calling
fo_close (see kern_descrip.c).
I cannot find the statement in SUSv3 that would require interruption of
the read() upon close() from another thread; this looks like undefined
behaviour from the standard point of view.
I think that JVM is more appropriate place for fix, but others may have
different view point.
Attachment:
pgpZQhf6IgAcM.pgp
Description: PGP signature
- Follow-Ups:
- Re: close() of active socket does not work on FreeBSD 6
- From: Arne H. Juul
- Re: close() of active socket does not work on FreeBSD 6
- Prev by Date: Re: Where do MSI quirks belong? [patch]
- Next by Date: Re: close() of active socket does not work on FreeBSD 6
- Previous by thread: Re: Where do MSI quirks belong? [patch]
- Next by thread: Re: close() of active socket does not work on FreeBSD 6
- Index(es):
Relevant Pages
|
|