8233002: Further enhance datagram socket support

Reviewed-by: alanb, chegar, dfuchs
This commit is contained in:
Ivan Gerasimov 2019-10-29 09:51:37 -07:00
parent c5f884c6d1
commit 34e36a8c01
4 changed files with 36 additions and 16 deletions

View File

@ -97,7 +97,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
fd = new FileDescriptor(); fd = new FileDescriptor();
try { try {
datagramSocketCreate(); datagramSocketCreate();
SocketCleanable.register(fd); SocketCleanable.register(fd, false);
} catch (SocketException ioe) { } catch (SocketException ioe) {
ResourceManager.afterUdpClose(); ResourceManager.afterUdpClose();
fd = null; fd = null;

View File

@ -127,7 +127,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
fd = new FileDescriptor(); fd = new FileDescriptor();
try { try {
socketCreate(false); socketCreate(false);
SocketCleanable.register(fd); SocketCleanable.register(fd, false);
} catch (IOException ioe) { } catch (IOException ioe) {
ResourceManager.afterUdpClose(); ResourceManager.afterUdpClose();
fd = null; fd = null;
@ -136,7 +136,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
} else { } else {
fd = new FileDescriptor(); fd = new FileDescriptor();
socketCreate(true); socketCreate(true);
SocketCleanable.register(fd); SocketCleanable.register(fd, true);
} }
} }
@ -580,7 +580,7 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
} finally { } finally {
releaseFD(); releaseFD();
} }
SocketCleanable.register(si.fd); SocketCleanable.register(si.fd, true);
} }
/** /**
@ -683,9 +683,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
protected void close() throws IOException { protected void close() throws IOException {
synchronized(fdLock) { synchronized(fdLock) {
if (fd != null) { if (fd != null) {
if (!stream) {
ResourceManager.afterUdpClose();
}
if (fdUseCount == 0) { if (fdUseCount == 0) {
if (closePending) { if (closePending) {
return; return;
@ -840,7 +837,13 @@ abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSoc
*/ */
protected void socketClose() throws IOException { protected void socketClose() throws IOException {
SocketCleanable.unregister(fd); SocketCleanable.unregister(fd);
socketClose0(false); try {
socketClose0(false);
} finally {
if (!stream) {
ResourceManager.afterUdpClose();
}
}
} }
abstract void socketCreate(boolean stream) throws IOException; abstract void socketCreate(boolean stream) throws IOException;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -34,6 +34,7 @@ import java.io.IOException;
import java.io.UncheckedIOException; import java.io.UncheckedIOException;
import java.lang.ref.Cleaner; import java.lang.ref.Cleaner;
import sun.net.ResourceManager;
/** /**
* Cleanable for a socket/datagramsocket FileDescriptor when it becomes phantom reachable. * Cleanable for a socket/datagramsocket FileDescriptor when it becomes phantom reachable.
@ -56,17 +57,22 @@ final class SocketCleanable extends PhantomCleanable<FileDescriptor> {
// The raw fd to close // The raw fd to close
private final int fd; private final int fd;
// true for socket, false for datagram socket
private final boolean stream;
/** /**
* Register a socket specific Cleanable with the FileDescriptor * Register a socket specific Cleanable with the FileDescriptor
* if the FileDescriptor is non-null and the raw fd is != -1. * if the FileDescriptor is non-null and the raw fd is != -1.
* *
* @param fdo the FileDescriptor; may be null * @param fdo the FileDescriptor; may be null
* @param stream false for datagram socket
*/ */
static void register(FileDescriptor fdo) { static void register(FileDescriptor fdo, boolean stream) {
if (fdo != null && fdo.valid()) { if (fdo != null && fdo.valid()) {
int fd = fdAccess.get(fdo); int fd = fdAccess.get(fdo);
fdAccess.registerCleanup(fdo, fdAccess.registerCleanup(fdo,
new SocketCleanable(fdo, CleanerFactory.cleaner(), fd)); new SocketCleanable(fdo, CleanerFactory.cleaner(),
fd, stream));
} }
} }
@ -86,10 +92,13 @@ final class SocketCleanable extends PhantomCleanable<FileDescriptor> {
* @param obj the object to monitor * @param obj the object to monitor
* @param cleaner the cleaner * @param cleaner the cleaner
* @param fd file descriptor to close * @param fd file descriptor to close
* @param stream false for datagram socket
*/ */
private SocketCleanable(FileDescriptor obj, Cleaner cleaner, int fd) { private SocketCleanable(FileDescriptor obj, Cleaner cleaner,
int fd, boolean stream) {
super(obj, cleaner); super(obj, cleaner);
this.fd = fd; this.fd = fd;
this.stream = stream;
} }
/** /**
@ -101,6 +110,10 @@ final class SocketCleanable extends PhantomCleanable<FileDescriptor> {
cleanupClose0(fd); cleanupClose0(fd);
} catch (IOException ioe) { } catch (IOException ioe) {
throw new UncheckedIOException("close", ioe); throw new UncheckedIOException("close", ioe);
} finally {
if (!stream) {
ResourceManager.afterUdpClose();
}
} }
} }
} }

View File

@ -87,7 +87,9 @@ final class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocket
fd1 = new FileDescriptor(); fd1 = new FileDescriptor();
try { try {
super.create(); super.create();
SocketCleanable.register(fd1); // make SocketCleanable treat fd1 as a stream socket
// to avoid touching the counter in ResourceManager
SocketCleanable.register(fd1, true);
} catch (SocketException e) { } catch (SocketException e) {
fd1 = null; fd1 = null;
throw e; throw e;
@ -114,8 +116,10 @@ final class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocket
bind0(lport, laddr, exclusiveBind); bind0(lport, laddr, exclusiveBind);
SocketCleanable.register(fd); SocketCleanable.register(fd, false);
SocketCleanable.register(fd1); // make SocketCleanable treat fd1 as a stream socket
// to avoid touching the counter in ResourceManager
SocketCleanable.register(fd1, true);
} }
protected synchronized void receive(DatagramPacket p) protected synchronized void receive(DatagramPacket p)