You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2014/03/12 15:49:13 UTC

svn commit: r1576765 - /tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java

Author: remm
Date: Wed Mar 12 14:49:12 2014
New Revision: 1576765

URL: http://svn.apache.org/r1576765
Log:
Switch to a semaphore here (for the flush, since the previous one would have issues if run after non blocking writes).

Modified:
    tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java

Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java?rev=1576765&r1=1576764&r2=1576765&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/Nio2ServletOutputStream.java Wed Mar 12 14:49:12 2014
@@ -23,6 +23,7 @@ import java.nio.channels.AsynchronousClo
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.CompletionHandler;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -35,7 +36,7 @@ public class Nio2ServletOutputStream ext
     private final Nio2Channel channel;
     private final int maxWrite;
     private final CompletionHandler<Integer, SocketWrapper<Nio2Channel>> completionHandler;
-    private volatile boolean writePending = false;
+    private final Semaphore writePending = new Semaphore(1);
 
     public Nio2ServletOutputStream(SocketWrapper<Nio2Channel> socketWrapper) {
         super(socketWrapper);
@@ -49,20 +50,26 @@ public class Nio2ServletOutputStream ext
                         failed(new ClosedChannelException(), attachment);
                         return;
                     }
-                    writePending = false;
+                    writePending.release();
                 }
                 if (!Nio2Endpoint.isInline()) {
                     try {
                         onWritePossible();
                     } catch (IOException e) {
-                        failed(e, attachment);
+                        attachment.setError(true);
+                        onError(e);
+                        try {
+                            close();
+                        } catch (IOException ioe) {
+                            // Ignore
+                        }
                     }
                 }
             }
             @Override
             public void failed(Throwable exc, SocketWrapper<Nio2Channel> attachment) {
                 attachment.setError(true);
-                writePending = false;
+                writePending.release();
                 if (exc instanceof AsynchronousCloseException) {
                     // If already closed, don't call onError and close again
                     return;
@@ -99,7 +106,7 @@ public class Nio2ServletOutputStream ext
                 throw new EOFException();
             }
             count += writtenThisLoop;
-            if (!block && writePending) {
+            if (!block && writePending.availablePermits() == 0) {
                 // Prevent concurrent writes in non blocking mode,
                 // leftover data has to be buffered
                 return count;
@@ -131,12 +138,11 @@ public class Nio2ServletOutputStream ext
                 throw new IOException(e);
             }
         } else {
-            synchronized (completionHandler) {
-                if (!writePending) {
+            if (writePending.tryAcquire()) {
+                synchronized (completionHandler) {
                     buffer.clear();
                     buffer.put(b, off, len);
                     buffer.flip();
-                    writePending = true;
                     Nio2Endpoint.startInline();
                     channel.write(buffer, socketWrapper.getTimeout(), TimeUnit.MILLISECONDS, socketWrapper, completionHandler);
                     Nio2Endpoint.endInline();
@@ -150,7 +156,9 @@ public class Nio2ServletOutputStream ext
     @Override
     protected void doFlush() throws IOException {
         try {
-            if (!writePending) {
+            // Block until a possible non blocking write is done
+            if (writePending.tryAcquire(socketWrapper.getTimeout(), TimeUnit.MILLISECONDS)) {
+                writePending.release();
                 channel.flush().get(socketWrapper.getTimeout(), TimeUnit.MILLISECONDS);
             }
         } catch (InterruptedException | ExecutionException | TimeoutException e) {



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org