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

(ch) Separate blocking and non-blocking code paths

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P3
    • Resolution: Approved
    • Fix Version/s: 11
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Kind:
      behavioral
    • Compatibility Risk:
      low
    • Compatibility Risk Description:
      Hide
      The likelihood of code depending on existing behavior is low but the change is worthy of a release note. We do not propose to provide a means to enable pre JDK 11 behavior.

      Quoting from http://mail.openjdk.java.net/pipermail/nio-dev/2018-February/004746.html:

      "In terms of compatibility, there are two behavioral changes:

      1. If a thread's interrupt status is set and it invokes an I/O method on
      a channel configured non-blocking then the channel will not be closed.
      The original specification was vague on this point as it focused on
      threads blocking in I/O operations. Several people have complained
      bitterly over the years about the existing behavior so they will welcome
      this change. I haven't found anything yet that depends on long standing
      behavior but we will need to track this in a CSR anyway.

      2. configureBlocking will now block if there are pending I/O operations.
      The spec has always stated that it may block so it should not be a
      surprise but there may be some cases where code attempts to change a
      channel to non-blocking while another thread is doing on a blocking I/O
      operation on the channel. This method now coordinates with channel
      closing, something that has never been right in the implementation."
      Show
      The likelihood of code depending on existing behavior is low but the change is worthy of a release note. We do not propose to provide a means to enable pre JDK 11 behavior. Quoting from http://mail.openjdk.java.net/pipermail/nio-dev/2018-February/004746.html: "In terms of compatibility, there are two behavioral changes: 1. If a thread's interrupt status is set and it invokes an I/O method on a channel configured non-blocking then the channel will not be closed. The original specification was vague on this point as it focused on threads blocking in I/O operations. Several people have complained bitterly over the years about the existing behavior so they will welcome this change. I haven't found anything yet that depends on long standing behavior but we will need to track this in a CSR anyway. 2. configureBlocking will now block if there are pending I/O operations. The spec has always stated that it may block so it should not be a surprise but there may be some cases where code attempts to change a channel to non-blocking while another thread is doing on a blocking I/O operation on the channel. This method now coordinates with channel closing, something that has never been right in the implementation."
    • Interface Kind:
      Java API
    • Scope:
      Implementation

      Description

      Summary

      Improve the performance and reliability of the java.nio.channel.SelectableChannel implementations by separating the blocking and non-blocking code paths.

      Problem

      SocketChannel, ServerSocketChannel, DatagramChannel, Pipe.SourceChannel and Pipe.SinkChannel implement InterruptibleChannel so that blocking I/O operations can be interrupted (and the channel closed) by Thread.interrupt. This behavior is problematic for high-performance libraries that use non-blocking I/O. Interrupting a thread has the potential to close a random channel that the thread happens to perform an I/O operation on. In addition, the implementation of async close and interrupt has been highly problematic with reliability issues and complex synchronization adding significant overhead to performance critical code paths.

      Usability, reliability, and performance can been improved significantly by limiting interruption to channels that are configured blocking. However, re-implementing this complex area results in a few behavior changes:

      1. Invoking configureBlocking(true) on a selectable channel will now block until outstanding I/O operations have completed. The specification allows this but the implementation in the JDK didn't historically synchronize and so didn't block. While unlikely, this may be observable by code outside of the JDK that has assumed it can change a selectable channel to non-blocking whilst a thread is blocked in an I/O operation.

      2. Invoking an I/O operation on a channel configured non-blocking and with the interrupt status set no longer closes the channel. This will be welcomed by many but it's possible (although unlikely) that something depends on long standing and unspecified behavior.

      3. Closing a connected SocketChannel that is registered with a Selector will delay closing the connection until the closed channel is flushed from all Selectors that it is registered with. The long standing behavior has been to close the connection (at least on Linux and macOS, not Windows) and to delay closing the file descriptor until the closed channel is flushed from all Selectors. The change is necessary for reliability reasons but it may be observed in environments that do not perform any selection operations to flush closed channels. To mitigate this behavior change, the implementation will shutdown the connection for writing so that at least the peer will read EOF. However the new behavior may initially puzzle developers that use netstat and other networking tools to get information about network connections.

      Solution

      Re-implement the I/O operations (read, write, accept, connect, finishConnect) defined by SocketChannel, ServerSocketChannel, DatagramChannel, Pipe.SourceChannel and Pipe.SinkChannel. When configured blocking, any thread that potentially blocks on an I/O operation can be interrupted so that the I/O operation is aborted and the channel closed as per the InterruptibleChannel specification. When configured non-blocking threads doing non-blocking I/O operations can be interrupted (meaning their interrupt status is set) but the channel is not closed.

      Specification

      There are no specification changes as InterruptibleChannel does not specify the behavior for non-blocking I/O operations.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                alanb Alan Bateman
                Reporter:
                alanb Alan Bateman
                Reviewed By:
                Brian Burkhalter
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: