Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8067846

(sctp) InternalError when receiving SendFailedNotification

XMLWordPrintable

    • b52
    • x86
    • linux_redhat_6.0
    • Verified

        FULL PRODUCT VERSION :
        java version "1.8.0_25"
        Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
        Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)


        ADDITIONAL OS VERSION INFORMATION :
        Linux pclt-henjoh 3.16.0-25-generic #33-Ubuntu SMP Tue Nov 4 12:06:54 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

        EXTRA RELEVANT SYSTEM CONFIGURATION :
        lksctp-tools 1.0.16

        A DESCRIPTION OF THE PROBLEM :
        JVM exits with InternalError when calling SctpMultiChannel.receive

        If a remote address which I am trying to send a packet to is down / not listening,
        I get a "java.lang.InternalError: should not reach here" error in SctpMultiChannel.receive,
        if the payload of my SctpMultiChannel.send call was 101 bytes or more.

        If I use a payload of 100 bytes or less,
        I get a sun.nio.ch.sctp.SendFailed notification instead, which seems more correct and is what I would expect.

        This behaviour was introduced in Java 1.8.0_20, and does not exist in 1.8.0_11 and earlier.
        (It also exists in Java 1.7.0_60 and later but not in 1.7.0_55 and earlier.)


        REGRESSION. Last worked in version 8u11

        ADDITIONAL REGRESSION INFORMATION:
        java version "1.8.0_11"
        Java(TM) SE Runtime Environment (build 1.8.0_11-b12)
        Java HotSpot(TM) 64-Bit Server VM (build 25.11-b03, mixed mode)


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Run provided test program with Java 1.8.0_25 to reproduce the problem.
        Run provided test program with Java 1.8.0_11 or earlier to see that it worked before.

        The test program first shows that 100 bytes works and then that 101 bytes fails:
        1. SctpMultiChannel.send(ByteBuffer.allocate(100 bytes), remoteAddressNotListening);
        2. SctpMultiChannel.receive( notificationhandler )
        3. SctpMultiChannel.receive( notificationhandler)

        4. SctpMultiChannel.send(ByteBuffer.allocate(101 bytes), remoteAddressNotListening);
        5. SctpMultiChannel.receive( notificationhandler )
        6. SctpMultiChannel.receive( notificationhandler )



        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        1. SctpMultiChannel.send(ByteBuffer.allocate(100 bytes), remoteAddressNotListening);
        2. SctpMultiChannel.receive( NotificationHandler AssociationChangeEvent CANT_START )
        3. SctpMultiChannel.receive( NotificationHandler SendFailed )

        4. SctpMultiChannel.send(ByteBuffer.allocate(101 bytes), remoteAddressNotListening);
        5. SctpMultiChannel.receive( NotificationHandler AssociationChangeEvent CANT_START )
        6. SctpMultiChannel.receive( NotificationHandler SendFailed )
        ACTUAL -
        1. SctpMultiChannel.send(ByteBuffer.allocate(100 bytes), remoteAddressNotListening);
        2. SctpMultiChannel.receive( NotificationHandler AssociationChangeEvent CANT_START )
        3. SctpMultiChannel.receive( NotificationHandler SendFailed )

        4. SctpMultiChannel.send(ByteBuffer.allocate(101 bytes), remoteAddressNotListening);
        5. SctpMultiChannel.receive( NotificationHandler AssociationChangeEvent CANT_START )
        6. SctpMultiChannel.receive( ) "java.lang.InternalError: should not reach here"

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
            Exception in thread "main" java.lang.InternalError: should not reach here
                at sun.nio.ch.sctp.SctpChannelImpl.receive0(Native Method)
                at sun.nio.ch.sctp.SctpMultiChannelImpl.receive0(SctpMultiChannelImpl.java:978)
                at sun.nio.ch.sctp.SctpMultiChannelImpl.receiveIntoNativeBuffer(SctpMultiChannelImpl.java:582)
                at sun.nio.ch.sctp.SctpMultiChannelImpl.receive(SctpMultiChannelImpl.java:566)
                at sun.nio.ch.sctp.SctpMultiChannelImpl.receive(SctpMultiChannelImpl.java:496)
                at Main.send(Main.java:96)
                at Main.main(Main.java:61)

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import com.sun.nio.sctp.HandlerResult;
        import com.sun.nio.sctp.MessageInfo;
        import com.sun.nio.sctp.Notification;
        import com.sun.nio.sctp.NotificationHandler;
        import com.sun.nio.sctp.SctpMultiChannel;
        import com.sun.nio.sctp.SctpStandardSocketOptions;
        import com.sun.nio.sctp.SctpStandardSocketOptions.InitMaxStreams;

        import java.net.InetSocketAddress;
        import java.net.SocketAddress;
        import java.nio.ByteBuffer;
        import java.util.Arrays;
        import java.util.Date;
        import java.util.List;

        /**
         * This test tries to connect to a remote address, which is down, using the SCTP protocol.
         * It uses SctpMultiChannel to initiate an implicit association by sending a packet to the remote side.
         *
         * On Linux, the packet "is sent" and I can use my NotificationHandler to receive CANT_START and SendFailed notifications.
         * On Solaris, the SctpMultiChannel.send() throws a java.net.ConnectException: Connection refused.
         *
         * It seems the size of this packet matters in newer Java versions than 1.8u11/1.7u55.
         * If I use 1.8u20/1.7u60, or later, I cannot use more than 100 bytes in the initial packet
         * without getting an InternalError instead of a SendFailed notification.
         *
         */
        public class Main {

            static SocketAddress localSocketAddress = new InetSocketAddress("127.0.0.1", 2000);
            static SocketAddress remoteSocketAddress = new InetSocketAddress("127.0.0.1", 3000);

            public static void main(final String[] args) {

                if(args.length == 4) {
                    try {
                        localSocketAddress = new InetSocketAddress(args[0], Integer.parseInt(args[1]));
                        remoteSocketAddress = new InetSocketAddress(args[2], Integer.parseInt(args[3]));
                    } catch(Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("Usage: java Main <localip> <localport> <remoteip> <remoteport>");
                }

                System.out.println("Using local address: " + localSocketAddress);
                System.out.println("Using remote address: " + remoteSocketAddress);
                System.out.println("Note, remote address should not be up");


                printSystemInfo();

                final Main main = new Main();

                // This will work
                main.send(100);


                // This will fail,
                // on Linux with newer Java than 1.8u11/1.7u55
                main.send(101);
            }



            public void send(final int sendBufferSize) {
                System.out.println("==== Trying with " + sendBufferSize + " byte send buffer ====");
                try (final SctpMultiChannel sctpMultiChannel = SctpMultiChannel.open()) {
                    sctpMultiChannel.setOption(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS, InitMaxStreams.create(1, 1), null);

                    sctpMultiChannel.bind(localSocketAddress);

                    final MessageInfo messageInfo = MessageInfo.createOutgoing(remoteSocketAddress, 0);

                    System.out.println("Sending connection attempt to " + remoteSocketAddress.toString());
                    final int sent = sctpMultiChannel.send(ByteBuffer.allocate(sendBufferSize), messageInfo);
                    System.out.println("Sent " + sent);

                    final NotificationHandler notificationHandler = new NotificationHandler<Object>() {
                        @Override
                        public HandlerResult handleNotification(Notification notification, Object o) {
                            System.out.println("Notification: " + notification);
                            return HandlerResult.RETURN;
                        }
                    };

                    final ByteBuffer receiveByteBuffer = ByteBuffer.allocate(1024);

                    receiveByteBuffer.clear();
                    System.out.println("First receive on SctpMultiChannel");
                    final MessageInfo receivedMessageInfo1 = sctpMultiChannel.receive(receiveByteBuffer, null, notificationHandler);


                    receiveByteBuffer.clear();
                    System.out.println("Second receive on SctpMultiChannel");
                    final MessageInfo receivedMessageInfo2 = sctpMultiChannel.receive(receiveByteBuffer, null, notificationHandler);

                    System.out.println("No InternalError, success!\n");

                } catch (final Exception e) {
                    e.printStackTrace();
                }
            }



            private static void printSystemInfo() {
                final List<String> properties = Arrays.asList(
                        "os.name", "os.arch", "os.version",
                        "java.runtime.version",
                        "java.vm.specification.vendor");

                for(final String property : properties) {
                    System.out.println(property + ": " + System.getProperty(property));
                }
            }

        }

        ---------- END SOURCE ----------

              chegar Chris Hegarty
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: