--- old/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java 2019-06-04 12:43:02.000000000 +0100 +++ new/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java 2019-06-04 12:43:01.000000000 +0100 @@ -446,7 +446,10 @@ } else if (name == StandardSocketOptions.SO_REUSEPORT) { setOption(SocketOptions.SO_REUSEPORT, value); } else if (name == StandardSocketOptions.SO_LINGER ) { - setOption(SocketOptions.SO_LINGER, value); + if (((Integer)value).intValue() < 0) + setOption(SocketOptions.SO_LINGER, false); + else + setOption(SocketOptions.SO_LINGER, value); } else if (name == StandardSocketOptions.IP_TOS) { int i = ((Integer)value).intValue(); if (i < 0 || i > 255) @@ -482,7 +485,12 @@ } else if (name == StandardSocketOptions.SO_REUSEPORT) { return (T)getOption(SocketOptions.SO_REUSEPORT); } else if (name == StandardSocketOptions.SO_LINGER) { - return (T)getOption(SocketOptions.SO_LINGER); + Object value = getOption(SocketOptions.SO_LINGER); + if (value instanceof Boolean) { + assert ((Boolean)value).booleanValue() == false; + value = -1; + } + return (T)value; } else if (name == StandardSocketOptions.IP_TOS) { return (T)getOption(SocketOptions.IP_TOS); } else if (name == StandardSocketOptions.TCP_NODELAY) { --- old/test/jdk/java/net/SocketOption/OptionsTest.java 2019-06-04 12:43:03.000000000 +0100 +++ new/test/jdk/java/net/SocketOption/OptionsTest.java 2019-06-04 12:43:03.000000000 +0100 @@ -23,10 +23,11 @@ /* * @test - * @bug 8036979 8072384 8044773 + * @bug 8036979 8072384 8044773 8225214 * @library /test/lib * @requires !vm.graal.enabled * @run main/othervm -Xcheck:jni OptionsTest + * @run main/othervm -Djdk.net.usePlainSocketImpl OptionsTest * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest * @run main/othervm --limit-modules=java.base OptionsTest */ @@ -52,7 +53,7 @@ } // The tests set the option using the new API, read back the set value - // which could be diferent, and then use the legacy get API to check + // which could be different, and then use the legacy get API to check // these values are the same static Test[] socketTests = new Test[] { @@ -61,6 +62,8 @@ Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(-1)), + Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(0)), Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(0)), // lower-bound Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)), @@ -234,7 +237,7 @@ } else if (option.equals(StandardSocketOptions.TCP_NODELAY)) { return Boolean.valueOf(socket.getTcpNoDelay()); } else { - throw new RuntimeException("unexecpted socket option"); + throw new RuntimeException("unexpected socket option"); } } else if (type.equals(ServerSocket.class)) { ServerSocket socket = (ServerSocket)s; @@ -250,7 +253,7 @@ } else if (option.equals(StandardSocketOptions.IP_TOS)) { return getServerSocketTrafficClass(socket); } else { - throw new RuntimeException("unexecpted socket option"); + throw new RuntimeException("unexpected socket option"); } } else if (type.equals(DatagramSocket.class)) { DatagramSocket socket = (DatagramSocket)s; @@ -268,7 +271,7 @@ } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(socket.getTrafficClass()); } else { - throw new RuntimeException("unexecpted socket option"); + throw new RuntimeException("unexpected socket option"); } } else if (type.equals(MulticastSocket.class)) { @@ -293,10 +296,26 @@ } else if (option.equals(StandardSocketOptions.IP_MULTICAST_LOOP)) { return Boolean.valueOf(socket.getLoopbackMode()); } else { - throw new RuntimeException("unexecpted socket option"); + throw new RuntimeException("unexpected socket option"); + } + } + throw new RuntimeException("unexpected socket type"); + } + + // Tests default and negative values of SO_LINGER. All negative values should + // retrieve as -1. + public static void soLinger() throws Exception { + try (Socket s = new Socket()) { + // retrieve without set + int ignoreValue = s.getOption(StandardSocketOptions.SO_LINGER); + + for (int v : List.of(-1, -2, -100, -65534, -65535, -65536, -100000)) { + System.out.println("Testing SO_LINGER with:" + v); + s.setOption(StandardSocketOptions.SO_LINGER, v); + int value = s.getOption(StandardSocketOptions.SO_LINGER); + testEqual(StandardSocketOptions.SO_LINGER, -1, value); } } - throw new RuntimeException("unexecpted socket type"); } public static void main(String args[]) throws Exception { @@ -305,6 +324,7 @@ doServerSocketTests(); doDatagramSocketTests(); doMulticastSocketTests(); + soLinger(); } // Reflectively access jdk.net.Sockets.getOption so that the test can run