Skip site navigation (1)Skip section navigation (2)
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>