Author: markt Date: Mon Mar 11 20:30:49 2013 New Revision: 1455314 URL: http://svn.apache.org/r1455314 Log: APR read/write need to use the same locks for changing the blocking status of the socket
Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java?rev=1455314&r1=1455313&r2=1455314&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletInputStream.java Mon Mar 11 20:30:49 2013 @@ -18,7 +18,6 @@ package org.apache.coyote.http11.upgrade import java.io.IOException; import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.apache.tomcat.jni.Socket; @@ -29,8 +28,6 @@ public class AprServletInputStream exten private final SocketWrapper<Long> wrapper; private final long socket; - private final Lock blockingStatusReadLock; - private final WriteLock blockingStatusWriteLock; private volatile boolean eagain = false; private volatile boolean closed = false; @@ -38,9 +35,6 @@ public class AprServletInputStream exten public AprServletInputStream(SocketWrapper<Long> wrapper) { this.wrapper = wrapper; this.socket = wrapper.getSocket().longValue(); - ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - this.blockingStatusReadLock = lock.readLock(); - this.blockingStatusWriteLock =lock.writeLock(); } @@ -48,10 +42,13 @@ public class AprServletInputStream exten protected int doRead(boolean block, byte[] b, int off, int len) throws IOException { + Lock readLock = wrapper.getBlockingStatusReadLock(); + WriteLock writeLock = wrapper.getBlockingStatusWriteLock(); + boolean readDone = false; int result = 0; try { - blockingStatusReadLock.lock(); + readLock.lock(); if (wrapper.getBlockingStatus() == block) { if (closed) { throw new IOException(sm.getString("apr.closed")); @@ -60,31 +57,31 @@ public class AprServletInputStream exten readDone = true; } } finally { - blockingStatusReadLock.unlock(); + readLock.unlock(); } if (!readDone) { try { - blockingStatusWriteLock.lock(); + writeLock.lock(); wrapper.setBlockingStatus(block); // Set the current settings for this socket Socket.optSet(socket, Socket.APR_SO_NONBLOCK, (block ? 0 : 1)); // Downgrade the lock try { - blockingStatusReadLock.lock(); - blockingStatusWriteLock.unlock(); + readLock.lock(); + writeLock.unlock(); if (closed) { throw new IOException(sm.getString("apr.closed")); } result = Socket.recv(socket, b, off, len); } finally { - blockingStatusReadLock.unlock(); + readLock.unlock(); } } finally { // Should have been released above but may not have been on some // exception paths - if (blockingStatusWriteLock.isHeldByCurrentThread()) { - blockingStatusWriteLock.unlock(); + if (writeLock.isHeldByCurrentThread()) { + writeLock.unlock(); } } } Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java?rev=1455314&r1=1455313&r2=1455314&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/AprServletOutputStream.java Mon Mar 11 20:30:49 2013 @@ -18,7 +18,6 @@ package org.apache.coyote.http11.upgrade import java.io.IOException; import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; import org.apache.tomcat.jni.Socket; @@ -31,8 +30,6 @@ public class AprServletOutputStream exte private final AprEndpoint endpoint; private final SocketWrapper<Long> wrapper; private final long socket; - private final Lock blockingStatusReadLock; - private final WriteLock blockingStatusWriteLock; private volatile boolean closed = false; public AprServletOutputStream(SocketWrapper<Long> wrapper, @@ -40,9 +37,6 @@ public class AprServletOutputStream exte this.endpoint = endpoint; this.wrapper = wrapper; this.socket = wrapper.getSocket().longValue(); - ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - this.blockingStatusReadLock = lock.readLock(); - this.blockingStatusWriteLock =lock.writeLock(); } @@ -50,10 +44,13 @@ public class AprServletOutputStream exte protected int doWrite(boolean block, byte[] b, int off, int len) throws IOException { + Lock readLock = wrapper.getBlockingStatusReadLock(); + WriteLock writeLock = wrapper.getBlockingStatusWriteLock(); + boolean writeDone = false; int result = 0; try { - blockingStatusReadLock.lock(); + readLock.lock(); if (wrapper.getBlockingStatus() == block) { if (closed) { throw new IOException(sm.getString("apr.closed")); @@ -62,31 +59,31 @@ public class AprServletOutputStream exte writeDone = true; } } finally { - blockingStatusReadLock.unlock(); + readLock.unlock(); } if (!writeDone) { try { - blockingStatusWriteLock.lock(); + writeLock.lock(); wrapper.setBlockingStatus(block); // Set the current settings for this socket Socket.optSet(socket, Socket.APR_SO_NONBLOCK, (block ? -1 : 0)); // Downgrade the lock try { - blockingStatusReadLock.lock(); - blockingStatusWriteLock.unlock(); + readLock.lock(); + writeLock.unlock(); if (closed) { throw new IOException(sm.getString("apr.closed")); } result = Socket.send(socket, b, off, len); } finally { - blockingStatusReadLock.unlock(); + readLock.unlock(); } } finally { // Should have been released above but may not have been on some // exception paths - if (blockingStatusWriteLock.isHeldByCurrentThread()) { - blockingStatusWriteLock.unlock(); + if (writeLock.isHeldByCurrentThread()) { + writeLock.unlock(); } } } @@ -96,8 +93,7 @@ public class AprServletOutputStream exte endpoint.getPoller().add(socket, -1, false, true); } return result; - } - else if (-result == Status.EAGAIN) { + } else if (-result == Status.EAGAIN) { endpoint.getPoller().add(socket, -1, false, true); return 0; } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java?rev=1455314&r1=1455313&r2=1455314&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java Mon Mar 11 20:30:49 2013 @@ -16,6 +16,10 @@ */ package org.apache.tomcat.util.net; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; + public class SocketWrapper<E> { protected volatile E socket; @@ -39,12 +43,18 @@ public class SocketWrapper<E> { private String remoteAddr = null; /* * Used if block/non-blocking is set at the socket level. The client is - * responsible for the thread-safe use of this field. + * responsible for the thread-safe use of this field via the locks provided. */ private volatile boolean blockingStatus = true; + private final Lock blockingStatusReadLock; + private final WriteLock blockingStatusWriteLock; + public SocketWrapper(E socket) { this.socket = socket; + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + this.blockingStatusReadLock = lock.readLock(); + this.blockingStatusWriteLock =lock.writeLock(); } public E getSocket() { @@ -84,4 +94,8 @@ public class SocketWrapper<E> { public void setBlockingStatus(boolean blockingStatus) { this.blockingStatus = blockingStatus; } + public Lock getBlockingStatusReadLock() { return blockingStatusReadLock; } + public WriteLock getBlockingStatusWriteLock() { + return blockingStatusWriteLock; + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org