Skip to content

Commit

Permalink
common: Allow disabling shutdown upon close; add AFSomeSocketThing
Browse files Browse the repository at this point in the history
We may not always want to call shutdown on a socket. Add an option to
disable this.

While doing this, add "AFSomeSocketThing", which defines common methods
for all sorts of junixsocket-based socket types, including channels and
servers.
  • Loading branch information
kohlschuetter committed Feb 4, 2024
1 parent a5db9a6 commit 1720394
Show file tree
Hide file tree
Showing 13 changed files with 137 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,9 @@ public final boolean isDeleteOnClose() {
public final void setDeleteOnClose(boolean b) {
afSocket.setDeleteOnClose(b);
}

@Override
public void setShutdownOnClose(boolean enabled) {
getAFCore().setShutdownOnClose(enabled);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -525,4 +525,9 @@ AFDatagramSocket<A> accept1(boolean throwOnFail) throws IOException {

return as;
}

@Override
public void setShutdownOnClose(boolean enabled) {
getAFImpl().getCore().setShutdownOnClose(enabled);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -441,10 +441,12 @@ final boolean accept0(AFDatagramSocketImpl<A> socket) throws IOException {
caught = e;
} finally { // NOPMD.DoNotThrowExceptionInFinally
if (!isBound() || isClosed()) {
try {
NativeUnixSocket.shutdown(si.fd, SHUT_RD_WR);
} catch (Exception e) {
// ignore
if (getCore().isShutdownOnClose()) {
try {
NativeUnixSocket.shutdown(si.fd, SHUT_RD_WR);
} catch (Exception e) {
// ignore
}
}
try {
NativeUnixSocket.close(si.fd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
* @author Christian Kohlschütter
*/
@NonNullByDefault
final class AFGenericSocketOptions {
final class AFGenericSocketOptions {
private AFGenericSocketOptions() {
throw new IllegalStateException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
*/
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.CouplingBetweenObjects"})
public abstract class AFServerSocket<A extends AFSocketAddress> extends ServerSocket implements
FileDescriptorAccess {
AFSomeSocketThing {
private final AFSocketImpl<A> implementation;
private @Nullable A boundEndpoint;
private final Closeables closeables = new Closeables();
Expand Down Expand Up @@ -657,6 +657,11 @@ public Set<SocketOption<?>> supportedOptions() {
return getAFImpl().supportedOptions();
}

@Override
public void setShutdownOnClose(boolean enabled) {
getAFImpl().getCore().setShutdownOnClose(enabled);
}

// NOTE: We shall re-implement all methods defined in ServerSocket that internally call getImpl()
// and call getAFImpl() here. This is not strictly necessary for environments where we can
// override "impl"; however it's the right thing to do.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,12 @@ public AFSocketChannel<A> accept() throws IOException {
}

@Override
public final @Nullable A getLocalAddress() throws IOException {
public final @Nullable A getLocalAddress() {
return getLocalSocketAddress();
}

@Override
public final @Nullable A getLocalSocketAddress() {
return afSocket.getLocalSocketAddress();
}

Expand Down Expand Up @@ -170,4 +175,10 @@ public final boolean isDeleteOnClose() {
public final void setDeleteOnClose(boolean b) {
socket().setDeleteOnClose(b);
}

@Override
public void setShutdownOnClose(boolean enabled) {
socket().setShutdownOnClose(enabled);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -620,4 +620,9 @@ public boolean checkConnectionClosed() throws IOException {
public static boolean isRunningOnAndroid() {
return NativeLibraryLoader.isAndroid();
}

@Override
public void setShutdownOnClose(boolean enabled) {
getAFImpl().getCore().setShutdownOnClose(enabled);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -304,4 +304,9 @@ public final FileDescriptor getFileDescriptor() throws IOException {
public final String toString() {
return super.toString() + afSocket.toStringSuffix();
}

@Override
public void setShutdownOnClose(boolean enabled) {
getAFCore().setShutdownOnClose(enabled);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class AFSocketCore extends AFCore {
AFSocketAddress socketAddress;

private final AFAddressFamily<?> af;
private boolean shutdownOnClose = true;

protected AFSocketCore(Object observed, FileDescriptor fd,
AncillaryDataSupport ancillaryDataSupport, AFAddressFamily<?> af, boolean datagramMode) {
Expand All @@ -56,8 +57,10 @@ protected AFAddressFamily<?> addressFamily() {
@Override
@SuppressWarnings("UnsafeFinalization" /* errorprone */)
protected void doClose() throws IOException {
NativeUnixSocket.shutdown(fd, SHUT_RD_WR);
unblockAccepts();
if (isShutdownOnClose()) {
NativeUnixSocket.shutdown(fd, SHUT_RD_WR);
unblockAccepts();
}

super.doClose();
}
Expand Down Expand Up @@ -151,4 +154,12 @@ protected void decPendingAccepts() throws SocketException {
protected boolean hasPendingAccepts() {
return pendingAccepts.get() > 0;
}

boolean isShutdownOnClose() {
return shutdownOnClose;
}

void setShutdownOnClose(boolean enabled) {
this.shutdownOnClose = enabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,12 @@ protected void unblockAccepts() {
// (e.g., SocketException: No such file or directory)
return;
}
try {
NativeUnixSocket.shutdown(tmpFd, SHUT_RD_WR);
} catch (Exception e) {
// ignore
if (isShutdownOnClose()) {
try {
NativeUnixSocket.shutdown(tmpFd, SHUT_RD_WR);
} catch (Exception e) {
// ignore
}
}
try {
NativeUnixSocket.close(tmpFd);
Expand Down Expand Up @@ -256,10 +258,12 @@ final boolean accept0(SocketImpl socket) throws IOException {
caught = e;
} finally { // NOPMD.DoNotThrowExceptionInFinally
if (!isBound() || isClosed()) {
try {
NativeUnixSocket.shutdown(si.fd, SHUT_RD_WR);
} catch (Exception e) {
// ignore
if (getCore().isShutdownOnClose()) {
try {
NativeUnixSocket.shutdown(si.fd, SHUT_RD_WR);
} catch (Exception e) {
// ignore
}
}
try {
NativeUnixSocket.close(si.fd);
Expand Down Expand Up @@ -517,7 +521,7 @@ public int read() throws IOException {
public synchronized void close() throws IOException {
streamClosed = true;
FileDescriptor fdesc = core.validFd();
if (fdesc != null) {
if (fdesc != null && getCore().isShutdownOnClose()) {
NativeUnixSocket.shutdown(fdesc, SHUT_RD);
}

Expand Down Expand Up @@ -617,7 +621,7 @@ public synchronized void close() throws IOException {
}
streamClosed = true;
FileDescriptor fdesc = core.validFd();
if (fdesc != null) {
if (fdesc != null && getCore().isShutdownOnClose()) {
NativeUnixSocket.shutdown(fdesc, SHUT_WR);
}
closedOutputStream = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package org.newsclub.net.unix;

import java.io.Closeable;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketAddress;
Expand All @@ -37,16 +36,7 @@
* @see AFDatagramSocket
* @see AFDatagramChannel
*/
public interface AFSomeSocket extends Closeable, FileDescriptorAccess {
/**
* Returns the socket's local socket address, or {@code null} if unavailable or if there was a
* problem retrieving it.
*
* @return The local socket address, or {@code null}.
*/
@Nullable
SocketAddress getLocalSocketAddress();

public interface AFSomeSocket extends AFSomeSocketThing {
/**
* Returns the socket's remote socket address, or {@code null} if unavailable/not connected, or if
* there was a problem retrieving it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
* @see AFServerSocketChannel
* @see AFDatagramChannel
*/
public interface AFSomeSocketChannel extends Closeable, FileDescriptorAccess {
public interface AFSomeSocketChannel extends Closeable, FileDescriptorAccess, AFSomeSocketThing {
/**
* Checks if the channel is configured blocking. The result may be cached, and therefore not
* invoke native code to check if the underlying socket is actually configured that way.
*
*
* @return {@code true} if blocking.
*/
boolean isBlocking();
Expand All @@ -49,7 +49,7 @@ public interface AFSomeSocketChannel extends Closeable, FileDescriptorAccess {
* If the given blocking mode is different from the currently cached blocking mode then this
* method native code to change it.
* </p>
*
*
* @param block {@code true} if blocking is desired.
* @return This channel.
* @throws IOException on error.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* junixsocket
*
* Copyright 2009-2023 Christian Kohlschütter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.newsclub.net.unix;

import java.io.Closeable;
import java.net.DatagramSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.DatagramChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

import org.eclipse.jdt.annotation.Nullable;

/**
* Marker interface that combines junixsocket-based {@link SocketChannel}s, {@link Socket}s,
* {@link DatagramChannel}s and {@link DatagramSocket}s, as well as {@link ServerSocket}s and
* {@link ServerSocketChannel}s.
*
* @author Christian Kohlschütter
* @see AFSocketPair
* @see AFSocket
* @see AFSocketChannel
* @see AFDatagramSocket
* @see AFDatagramChannel
* @see AFServerSocket
* @see AFServerSocketChannel
*/
public interface AFSomeSocketThing extends Closeable, FileDescriptorAccess {
/**
* Returns the socket's local socket address, or {@code null} if unavailable or if there was a
* problem retrieving it.
*
* @return The local socket address, or {@code null}.
*/
@Nullable
SocketAddress getLocalSocketAddress();

/**
* Configures whether the socket should be shutdown upon {@link #close()}, which is the default.
*
* @param enabled {@code true} if enabled.
*/
void setShutdownOnClose(boolean enabled);
}

0 comments on commit 1720394

Please sign in to comment.