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: [email protected]
For additional commands, e-mail: [email protected]