Hi Xuelei,

I am not an expert of the field so please get another
reviewer for this change:

 656                     if (!super.isOutputShutdown() &&
                         ...
 661                     } else if (!super.isOutputShutdown()) {

I think it might be clearer with a nested if:

   if (!super.isOutputShutdown()) {
       if (isLayered() && !autoClose) {
           throw exception ...
       } else {
           super.shutdownOutput();
           log ...
       }
   }

Could lines 630 .. 647 be moved to a private method?
Something like:

     private void handleClosedNotifyAlert() {
 630     try {
             // send a user_canceled alert if needed.
             if (useUserCanceled) {
                 conContext.warning(Alert.USER_CANCELED);
             }

             // send a close_notify alert
             conContext.warning(Alert.CLOSE_NOTIFY);
         } finally {
             if (!conContext.isOutboundClosed()) {
                 conContext.outputRecord.close();
             }

             if (!super.isOutputShutdown() &&
                     (autoClose || !isLayered())) {
                 super.shutdownOutput();
 647         }
          }
      }

because if I'm not mistaken this exact same piece of code
appears at lines 700 - 717.

I believe this would simplify this long method a little bit,
and possibly makes what is happening here clearer:

 623     if (linger >= 0) {
            // don't wait more than SO_LINGER for obtaining the
            // the lock...
             ...
 626         try {
 627             if (conContext.outputRecord.recordLock.tryLock() ||
 628                     conContext.outputRecord.recordLock.tryLock(
 629                             linger, TimeUnit.SECONDS)) {
                     try {
                         handleClosedNotifyAlert();
                     } finally {
                         conContext.outputRecord.recordLock.unlock();
                     }
 652             } else {
 653                 // For layered, non-autoclose sockets, we are not
 654                 // able to bring them into a usable state, so we
 655                 // treat it as fatal error.
                     ...
 688             }
 689         } catch (InterruptedException ex) {
               ...
 692         }
 693
 694         // restore the interrupted status
             ...
 698     } else {
 699         conContext.outputRecord.recordLock.lock();
 700         try {
                 handleClosedNotifyAlert();
             } finally {
                 conContext.outputRecord.recordLock.unlock();
             }
          }
          ...


BlockedAsyncClose.java:

   Can you bind the server to the loopback instead of the
   wildcard? My experience is that it make tests more reliable.

             InetAddress loopback = InetAddress.getLoopbackAddress();
  74         ss = (SSLServerSocket) sslssf.createServerSocket();
             ss.bind(new InetSosketAddress(loopback, 0));
  75
  76         SSLSocketFactory sslsf =
  77             (SSLSocketFactory)SSLSocketFactory.getDefault();
socket = (SSLSocket)sslsf.createSocket(loopback, ss.getLocalPort());


best regards,

-- daniel

On 12/06/2019 14:51, Xuelei Fan wrote:
ping ...

On 6/4/2019 11:10 AM, Xuelei Fan wrote:
Hi,

Could I get the following update reviewed?
    http://cr.openjdk.java.net/~xuelei/8224829/webrev.00/

If using one thread for closing, one thread for writing.  Closing and writing threads are synchronized in order to delivery close_notify TLS record.  There are could be race between the two threads.  If the output stream buffer reach the limit, the write will be blocked, and then the close thread may be pending.

The SO_LINGER is used to resolve the issue for general socket.  With the above update, the SSLSocket implementation will check the SO_LINGER as well.  If SO_LINGER is on, the SSLSocket close will try to get the synchronization lock in the time of SO_LINGER value.  If timeout, the close process will move on, and close the underlying socket by force.

Thanks,
Xuelei

Reply via email to