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>
