Date: Mon, 11 Dec 2006 19:11:15 +0200 From: Kostik Belousov <kostikbel@gmail.com> To: "Arne H. Juul" <arnej@pvv.ntnu.no> Cc: freebsd-arch@freebsd.org, freebsd-java@freebsd.org Subject: Re: close() of active socket does not work on FreeBSD 6 Message-ID: <20061211171115.GD311@deviant.kiev.zoral.com.ua> In-Reply-To: <Pine.LNX.4.62.0612111552480.16908@decibel.pvv.ntnu.no> References: <Pine.LNX.4.62.0612111535280.32258@decibel.pvv.ntnu.no> <Pine.LNX.4.62.0612111552480.16908@decibel.pvv.ntnu.no>
next in thread | previous in thread | raw e-mail | index | archive | help
--7qSK/uQB79J36Y4o Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable 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=20 > reopen the close()'d filedescriptor, making it point to a filedescriptor= =20 > that's pre-connected to a closed socket. >=20 > 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? >=20 > 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 >=20 >=20 > #include <fcntl.h> > #include <stdlib.h> > #include <stdio.h> > #include <unistd.h> > #include <pthread.h> >=20 > int p[2]; >=20 > void *run(void *arg) { > ssize_t res; > char tmp[128]; > fprintf(stderr, "reading...\n"); > res =3D read(p[0], tmp, sizeof(tmp)); > fprintf(stderr, "read result: %d\n", (int)res); > if (res < 0) { > perror("read"); > } > return arg; > } >=20 > int main(int argc, char **argv) { > pthread_t t; > int d =3D open("/dev/null", O_RDONLY); > if (pipe(p) !=3D 0) { > perror("pipe"); > return 1; > } > if (pthread_create(&t, NULL, run, NULL) !=3D 0) { > perror("thread create"); > return 1; > } > sleep(1); > d =3D 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) !=3D 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. --7qSK/uQB79J36Y4o Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (FreeBSD) iD8DBQFFfZEzC3+MBN1Mb4gRAqKBAJ0e2xoeobSLeRZjJQbFUs5/uXX3ywCgqkJM ZoWAOIyyznh7U1KYx8vpB8s= =CgYu -----END PGP SIGNATURE----- --7qSK/uQB79J36Y4o--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20061211171115.GD311>