JDK-8221248 : Specify behaviour of timeout accepting methods of Socket and ServerSocket if timeout is negative
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.net
  • Priority: P4
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 13
  • Submitted: 2019-03-21
  • Updated: 2019-09-24
  • Resolved: 2019-03-26
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Specify behaviour of the timeout accepting methods of `Socket` and
`ServerSocket`, when the given a negative timeout.

Problem
-------

The problem is that the specification of the following three methods
requires the given `timeout` argument to be non-negative, but does not
specify what happens if given a negative timeout value.

    ServerSocket.setSoTimeout(int timeout)
    Socket.seSoTimeout(int timeout)
    Socket.connect(SocketAddress address, int timeout)

Solution
--------

The solution is to document, in all three of the aforementioned methods,
that a negative `timeout` value will result in an
`IllegalArgumentException` being thrown.

The above methods already throw `IllegalArgumentException`, so this
change is effectively documenting existing long-standing behaviour.

Note: Before this change, `ServerSocket::setSoTimeout` defers the
timeout argument checking to its socket impl. The default plain socket
impl throws `IllegalArgumentException` if given a negative timeout. It
is possible, but unlikely, that an alternative custom socket impl could
have accepted a negative timeout, but the effects of such are
unspecified and unknown. After this change, ServerSocket will no longer
defer the timeout argument checking, it will check its own arguments.

Specification
-------------

src/java.base/share/classes/java/net/ServerSocket.java

     /**
      * Enable/disable {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT} with the
      * specified timeout, in milliseconds.  With this option set to a non-zero
      * timeout, a call to accept() for this ServerSocket
      * will block for only this amount of time.  If the timeout expires,
      * a <B>java.net.SocketTimeoutException</B> is raised, though the
      * ServerSocket is still valid.  The option <B>must</B> be enabled
      * prior to entering the blocking operation to have effect.  The
      * timeout must be {@code > 0}.
      * A timeout of zero is interpreted as an infinite timeout.
      * @param timeout the specified timeout, in milliseconds
      * @exception SocketException if there is an error in
      * the underlying protocol, such as a TCP error.
    + * @throws  IllegalArgumentException  if {@code timeout} is negative
      * @since   1.1
      * @see #getSoTimeout()
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException


src/java.base/share/classes/java/net/Socket.java

     /**
      * Connects this socket to the server with a specified timeout value.
      * A timeout of zero is interpreted as an infinite timeout. The connection
      * will then block until established or an error occurs.
      *
      * @param   endpoint the {@code SocketAddress}
      * @param   timeout  the timeout value to be used in milliseconds.
      * @throws  IOException if an error occurs during the connection
      * @throws  SocketTimeoutException if timeout expires before connecting
      * @throws  java.nio.channels.IllegalBlockingModeException
      *          if this socket has an associated channel,
      *          and the channel is in non-blocking mode
      * @throws  IllegalArgumentException if endpoint is null or is a
    - *          SocketAddress subclass not supported by this socket
    + *          SocketAddress subclass not supported by this socket, or
    + *          if {@code timeout} is negative
      * @since 1.4
      * @spec JSR-51
      */
     public void connect(SocketAddress endpoint, int timeout) throws IOException

      /**
       *  Enable/disable {@link SocketOptions#SO_TIMEOUT SO_TIMEOUT}
       *  with the specified timeout, in milliseconds. With this option set
       *  to a non-zero timeout, a read() call on the InputStream associated with
       *  this Socket will block for only this amount of time.  If the timeout
       *  expires, a <B>java.net.SocketTimeoutException</B> is raised, though the
       *  Socket is still valid. The option <B>must</B> be enabled
       *  prior to entering the blocking operation to have effect. The
       *  timeout must be {@code > 0}.
       *  A timeout of zero is interpreted as an infinite timeout.
       *
       * @param timeout the specified timeout, in milliseconds.
       * @exception SocketException if there is an error
       * in the underlying protocol, such as a TCP error.
     + * @throws  IllegalArgumentException if {@code timeout} is negative
       * @since   1.1
       * @see #getSoTimeout()
       */
      public synchronized void setSoTimeout(int timeout) throws SocketException

Comments
Moving to Approved.
26-03-2019