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

Switching to an infinite socket timeout on Windows leads to high CPU load

    Details

    • Subcomponent:
    • Introduced In Build:
      b24
    • Introduced In Version:
      13
    • Resolved In Build:
      b33
    • CPU:
      x86_64
    • OS:
      windows_10
    • Verification:
      Verified

      Backports

        Description

        ADDITIONAL SYSTEM INFORMATION :
        Windows 10
        openjdk version "13-ea" 2019-09-17
        OpenJDK Runtime Environment (build 13-ea+31)
        OpenJDK 64-Bit Server VM (build 13-ea+31, mixed mode, sharing)

        A DESCRIPTION OF THE PROBLEM :
        When passing a non-zero value to java.net.Socket.setSoTimeout and then back again causes high CPU load on the thread which is attempting to read from the socket. According to the API docs, a timeout of zero means infinite. From the application perspective, the read is blocking exactly as it should, but the socket implementation appears to be in an infinite polling loop of some kind without waiting. When data becomes available, the read returns as expected.

        REGRESSION : Last worked in version 12.0.2

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Connect a socket, and set the timeout to a legal non-zero value. The server side writes one byte. The client then reads the byte from the socket, and then sets the timeout to zero, which means infinite. A subsequent read by the client blocks indefinitely (as expected), but the CPU load isn't zero.

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Expect to see no CPU activity on the thread while waiting to read. This is the observed behavior when running the test using JDK 12.
        ACTUAL -
        The CPU load on the thread (and Java process) isn't zero when blocked.

        ---------- BEGIN SOURCE ----------
        import java.net.*;

        public class Test {
            public static void main(String[] args) throws Exception {
                ServerSocket ss = new ServerSocket(0);

                new Thread(() -> {
                    try {
                        Socket s = ss.accept();
                        s.getOutputStream().write(1);
                    } catch (Exception e) {
                    }
                }).start();

                Socket s = new Socket("localhost", ss.getLocalPort());
                System.out.println(s);

                s.setSoTimeout(9999999);
                s.getInputStream().read();
                s.setSoTimeout(0); // should reset to infinite timeout
                while (true) {
                    s.getInputStream().read();
                }
            }
        }
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Set the timeout to a very large non zero value, which is effectively infinite.

        FREQUENCY : always


          Attachments

          1. JI9061817.java
            0.7 kB
          2. 11_0_3output.PNG
            11_0_3output.PNG
            20 kB
          3. 14ea_output.PNG
            14ea_output.PNG
            26 kB

            Issue Links

              Activity

                People

                • Assignee:
                  michaelm Michael McMahon
                  Reporter:
                  webbuggrp Webbug Group
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  7 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: