[PATCH] jdk1.4.2, getsockname(), and ECONNRESET  
Author Message
landonf





PostPosted: 2005-6-22 2:33:00 Top

java-programmer, [PATCH] jdk1.4.2, getsockname(), and ECONNRESET
--Apple-Mail-4--662330866
Content-Type: multipart/mixed; boundary=Apple-Mail-3--662330884


--Apple-Mail-3--662330884
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
charset=ISO-8859-1;
format=flowed

In j2se/src/solaris/native/sun/nio/ch/Net.c, getsockname() is called to=20=

determine the local address and port of a socket.

Under both Linux and Solaris, getsockname() will only fail if invalid=20
arguments are provided. If getsockname() returns an error, Java throws=20=

a java.lang.Error.
On FreeBSD, getsockname() will also return an error with errno set to=20
ECONNRESET if the connection has been reset by the peer. Consequently,=20=

Java throws a java.lang.Error.

The only way to handle this without an API change is to check for=20
ECONNRESET; In the attached patch, if errno is set to=A0ECONNRESET we=20
fill in the sockaddr structure with a port of 0, an IP of INADDR_ANY,=20
and clear out the error.

Also, any comments on the thread-safe resolver patch?

Thanks,
-landonf

--Apple-Mail-3--662330884
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream; x-unix-mode=0644;
name="getsockname-1.diff"
Content-Disposition: attachment;
filename=getsockname-1.diff

Only in getsockname: cscope.out
diff -ru bsdjdk/j2se/src/solaris/native/sun/nio/ch/Net.c getsockname/j2se/src/solaris/native/sun/nio/ch/Net.c
--- bsdjdk/j2se/src/solaris/native/sun/nio/ch/Net.c Fri May 13 18:04:33 2005
+++ getsockname/j2se/src/solaris/native/sun/nio/ch/Net.c Sun May 29 01:32:32 2005
@@ -118,8 +118,30 @@
SOCKADDR sa;
int sa_len = SOCKADDR_LEN;
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+#ifdef _BSD_SOURCE
+ /*
+ * XXXBSD:
+ * ECONNRESET is specific to the BSDs. We can not return an error,
+ * as the calling Java code with raise a java.lang.Error given the expectation
+ * that getsockname() will never fail. According to the Single UNIX Specification,
+ * it shouldn't fail. As such, we just fill in generic values.
+ */
+ if (errno == ECONNRESET) {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *) &sa;
+ bzero(sin, sizeof(*sin));
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_family = AF_INET;
+ sin->sin_port = htonl(0);
+ sin->sin_addr.s_addr = INADDR_ANY;
+ } else {
+ handleSocketError(env, errno);
+ return -1;
+ }
+#else /* _BSD_SOURCE */
handleSocketError(env, errno);
return -1;
+#endif /* _BSD_SOURCE */
}
return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
}
@@ -131,8 +153,30 @@
int sa_len = SOCKADDR_LEN;
int port;
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+#ifdef _BSD_SOURCE
+ /*
+ * XXXBSD:
+ * ECONNRESET is specific to the BSDs. We can not return an error,
+ * as the calling Java code with raise a java.lang.Error with the expectation
+ * that getsockname() will never fail. According to the Single UNIX Specification,
+ * it shouldn't fail. As such, we just fill in generic values.
+ */
+ if (errno == ECONNRESET) {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *) &sa;
+ bzero(sin, sizeof(*sin));
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_family = AF_INET;
+ sin->sin_port = htonl(0);
+ sin->sin_addr.s_addr = INADDR_ANY;
+ } else {
+ handleSocketError(env, errno);
+ return NULL;
+ }
+#else /* _BSD_SOURCE */
handleSocketError(env, errno);
return NULL;
+#endif /* _BSD_SOURCE */
}
return NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
}

--Apple-Mail-3--662330884--

--Apple-Mail-4--662330866
content-type: application/pgp-signature; x-mac-type=70674453;
name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (Darwin)

iD8DBQFCuF1nlplZCE/15mMRAlrDAJ9rqNEWNaX6iAmWW4AQEZUVz4lX1gCfVig7
+Kz1+xJm32a/fQVBsibMm2Y=
=tLoZ
-----END PGP SIGNATURE-----

--Apple-Mail-4--662330866--

 
glewis





PostPosted: 2005-6-22 5:02:00 Top

java-programmer >> [PATCH] jdk1.4.2, getsockname(), and ECONNRESET Hi Landon,

On Tue, Jun 21, 2005 at 11:33:09AM -0700, Landon Fuller wrote:
> In j2se/src/solaris/native/sun/nio/ch/Net.c, getsockname() is called to
> determine the local address and port of a socket.
>
> Under both Linux and Solaris, getsockname() will only fail if invalid
> arguments are provided. If getsockname() returns an error, Java throws
> a java.lang.Error.
> On FreeBSD, getsockname() will also return an error with errno set to
> ECONNRESET if the connection has been reset by the peer. Consequently,
> Java throws a java.lang.Error.
>
> The only way to handle this without an API change is to check for
> ECONNRESET; In the attached patch, if errno is set to?ECONNRESET we
> fill in the sockaddr structure with a port of 0, an IP of INADDR_ANY,
> and clear out the error.

On Linux and/or Solaris, what happens when you call getsockname() on a
socket that has had the connection reset by the peer? In particular,
is it compatible with what your patch does or are we introducing a new
scenario that the socket code for applications must handle?

> Also, any comments on the thread-safe resolver patch?

My bad, I haven't gotten to testing it yet :(. One concern was that
you mention the routines you're using are thread safe under 5.4 and
better and I wondered if there was an impact on 4.x users? I will
try and get this tested soon, as I want it in the next patchset.

--
Greg Lewis Email : email***@***.com
Eyes Beyond Web : http://www.eyesbeyond.com
Information Technology FreeBSD : email***@***.com
_______________________________________________
email***@***.com mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-java
To unsubscribe, send any mail to "email***@***.com"
 
landonf





PostPosted: 2005-7-7 4:38:00 Top

java-programmer >> [PATCH] jdk1.4.2, getsockname(), and ECONNRESET -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Jun 21, 2005, at 14:01, Greg Lewis wrote:

> Hi Landon,
>
> On Linux and/or Solaris, what happens when you call getsockname() on a
> socket that has had the connection reset by the peer? In particular,
> is it compatible with what your patch does or are we introducing a new
> scenario that the socket code for applications must handle?

I looked over the Linux network implementation to be certain. When the
socket is reset, the source address and port are reset to 0. The kernel
handles IPv6 vs. IPv4 sockets, returning the correct sockaddr type.

In our case, we're only provided with the file descriptor, leaving us
with no means to discern whether the socket was formerly connected via
IPv4 or IPv6 - as such, we're forced to improvise by returning a
sockaddr_in if an error occurs. In terms of the localPort() method,
this makes no difference to the calling Java code as only the port
number is returned.

In the localAddress() method, returning an IPv4 address should not be
fatal. For localAddress() to in turn call getsockname(), the connect()
must have been issued without a bind() first being issued (otherwise,
java would have cached the local port and address previously). There
should be no expectation by the caller that either a Inet4Address or a
Inet6Address will be returned.

It would obviously be more correct to pass up the
java.net.SocketException (as opposed to the current java.lang.Error),
but our hands are tied by the published API.

>> Also, any comments on the thread-safe resolver patch?
>
> My bad, I haven't gotten to testing it yet :(. One concern was that
> you mention the routines you're using are thread safe under 5.4 and
> better and I wondered if there was an impact on 4.x users? I will
> try and get this tested soon, as I want it in the next patchset.

It's a good question. 4.x completely lacks a thread-safe resolver
library, and getaddrinfo() makes up for this by maintaining a Giant
lock on all resolver functions. This can result in painful delays while
threads block on name resolution.

Which is worse? Occasionally crashing java using the non-thread-safe
resolver, or potentially causing significant resolution delays? I worry
about the potential for breaking mostly-working installations. Then
again, the non-thread-safe resolver may already be doing a better job
of breaking them.

- -landonf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (Darwin)

iD8DBQFCzEEclplZCE/15mMRAvP8AKCLo5SBgTV/21zuz76QpkAW4BoH+QCfXyfN
c9kNkbmG9mbMhpZc2AXE/vY=
=Bxo3
-----END PGP SIGNATURE-----

_______________________________________________
email***@***.com mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-java
To unsubscribe, send any mail to "email***@***.com"
 
 
Landon Fuller





PostPosted: 2005-7-7 4:38:00 Top

java-programmer >> [PATCH] jdk1.4.2, getsockname(), and ECONNRESET -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Jun 21, 2005, at 14:01, Greg Lewis wrote:

> Hi Landon,
>
> On Linux and/or Solaris, what happens when you call getsockname() on a
> socket that has had the connection reset by the peer? In particular,
> is it compatible with what your patch does or are we introducing a new
> scenario that the socket code for applications must handle?

I looked over the Linux network implementation to be certain. When the
socket is reset, the source address and port are reset to 0. The kernel
handles IPv6 vs. IPv4 sockets, returning the correct sockaddr type.

In our case, we're only provided with the file descriptor, leaving us
with no means to discern whether the socket was formerly connected via
IPv4 or IPv6 - as such, we're forced to improvise by returning a
sockaddr_in if an error occurs. In terms of the localPort() method,
this makes no difference to the calling Java code as only the port
number is returned.

In the localAddress() method, returning an IPv4 address should not be
fatal. For localAddress() to in turn call getsockname(), the connect()
must have been issued without a bind() first being issued (otherwise,
java would have cached the local port and address previously). There
should be no expectation by the caller that either a Inet4Address or a
Inet6Address will be returned.

It would obviously be more correct to pass up the
java.net.SocketException (as opposed to the current java.lang.Error),
but our hands are tied by the published API.

>> Also, any comments on the thread-safe resolver patch?
>
> My bad, I haven't gotten to testing it yet :(. One concern was that
> you mention the routines you're using are thread safe under 5.4 and
> better and I wondered if there was an impact on 4.x users? I will
> try and get this tested soon, as I want it in the next patchset.

It's a good question. 4.x completely lacks a thread-safe resolver
library, and getaddrinfo() makes up for this by maintaining a Giant
lock on all resolver functions. This can result in painful delays while
threads block on name resolution.

Which is worse? Occasionally crashing java using the non-thread-safe
resolver, or potentially causing significant resolution delays? I worry
about the potential for breaking mostly-working installations. Then
again, the non-thread-safe resolver may already be doing a better job
of breaking them.

- -landonf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (Darwin)

iD8DBQFCzEEclplZCE/15mMRAvP8AKCLo5SBgTV/21zuz76QpkAW4BoH+QCfXyfN
c9kNkbmG9mbMhpZc2AXE/vY=
=Bxo3
-----END PGP SIGNATURE-----