JBossWeb SVN: r2550 - in branches/7.5.x/src/main/java/org: jboss/web and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-20 11:14:55 -0500 (Thu, 20 Nov 2014)
New Revision: 2550
Modified:
branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsSession.java
branches/7.5.x/src/main/java/org/jboss/web/WebsocketsLogger.java
Log:
Port upstream websocket fixes.
Modified: branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java 2014-11-18 23:08:31 UTC (rev 2549)
+++ branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java 2014-11-20 16:14:55 UTC (rev 2550)
@@ -304,12 +304,10 @@
boolean doWrite = false;
synchronized (messagePartLock) {
- if (Constants.OPCODE_CLOSE == mp.getOpCode()) {
- try {
- setBatchingAllowed(false);
- } catch (IOException e) {
- WebsocketsLogger.ROOT_LOGGER.flushOnCloseFailed(e);
- }
+ if (Constants.OPCODE_CLOSE == mp.getOpCode() && getBatchingAllowed()) {
+ // Should not happen. To late to send batched messages now since
+ // the session has been closed. Complain loudly.
+ WebsocketsLogger.ROOT_LOGGER.cannotFlushOnClose();
}
if (messagePartInProgress) {
// When a control message is sent while another message is being
@@ -382,7 +380,10 @@
if (Constants.INTERNAL_OPCODE_FLUSH == mp.getOpCode()) {
nextFragmented = fragmented;
nextText = text;
- doWrite(mp.getEndHandler(), outputBuffer);
+ outputBuffer.flip();
+ SendHandler flushHandler = new OutputBufferFlushSendHandler(
+ outputBuffer, mp.getEndHandler());
+ doWrite(flushHandler, outputBuffer);
return;
}
@@ -861,6 +862,30 @@
}
}
+
+ /**
+ * Ensures that the output buffer is cleared after it has been flushed.
+ */
+ private static class OutputBufferFlushSendHandler implements SendHandler {
+
+ private final ByteBuffer outputBuffer;
+ private final SendHandler handler;
+
+ public OutputBufferFlushSendHandler(ByteBuffer outputBuffer, SendHandler handler) {
+ this.outputBuffer = outputBuffer;
+ this.handler = handler;
+ }
+
+ @Override
+ public void onResult(SendResult result) {
+ if (result.isOK()) {
+ outputBuffer.clear();
+ }
+ handler.onResult(result);
+ }
+ }
+
+
private class WsOutputStream extends OutputStream {
private final WsRemoteEndpointImplBase endpoint;
Modified: branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsSession.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsSession.java 2014-11-18 23:08:31 UTC (rev 2549)
+++ branches/7.5.x/src/main/java/org/apache/tomcat/websocket/WsSession.java 2014-11-20 16:14:55 UTC (rev 2550)
@@ -425,6 +425,13 @@
return;
}
+ try {
+ wsRemoteEndpoint.setBatchingAllowed(false);
+ } catch (IOException e) {
+ WebsocketsLogger.ROOT_LOGGER.flushOnCloseFailed(e);
+ fireEndpointOnError(e);
+ }
+
state = State.CLOSING;
if (!Constants.RELAXED_CLOSE_EVENT) {
@@ -455,6 +462,12 @@
synchronized (stateLock) {
if (state == State.OPEN) {
+ try {
+ wsRemoteEndpoint.setBatchingAllowed(false);
+ } catch (IOException e) {
+ WebsocketsLogger.ROOT_LOGGER.flushOnCloseFailed(e);
+ fireEndpointOnError(e);
+ }
if (!Constants.RELAXED_CLOSE_EVENT) {
sendCloseMessage(closeReason);
fireEndpointOnClose(closeReason);
@@ -488,6 +501,20 @@
}
+ private void fireEndpointOnError(Throwable throwable) {
+
+ // Fire the onError event
+ Thread t = Thread.currentThread();
+ ClassLoader cl = t.getContextClassLoader();
+ t.setContextClassLoader(applicationClassLoader);
+ try {
+ localEndpoint.onError(this, throwable);
+ } finally {
+ t.setContextClassLoader(cl);
+ }
+ }
+
+
private void sendCloseMessage(CloseReason closeReason) {
// 125 is maximum size for the payload of a control message
ByteBuffer msg = ByteBuffer.allocate(125);
Modified: branches/7.5.x/src/main/java/org/jboss/web/WebsocketsLogger.java
===================================================================
--- branches/7.5.x/src/main/java/org/jboss/web/WebsocketsLogger.java 2014-11-18 23:08:31 UTC (rev 2549)
+++ branches/7.5.x/src/main/java/org/jboss/web/WebsocketsLogger.java 2014-11-20 16:14:55 UTC (rev 2550)
@@ -102,4 +102,8 @@
@Message(id = 8814, value = "Thread group %s not destroyed, %s threads left")
void threadGroupNotDestryed(String name, int threadCount);
+ @LogMessage(level = WARN)
+ @Message(id = 8815, value = "Cannot flush batched messages after closing the session")
+ void cannotFlushOnClose();
+
}
10 years, 1 month
JBossWeb SVN: r2549 - tags.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-18 18:08:31 -0500 (Tue, 18 Nov 2014)
New Revision: 2549
Added:
tags/JBOSSWEB_7_5_0_BETA6/
Log:
Beta6 build.
10 years, 1 month
JBossWeb SVN: r2548 - branches/7.5.x.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-18 18:08:09 -0500 (Tue, 18 Nov 2014)
New Revision: 2548
Modified:
branches/7.5.x/pom.xml
Log:
Beta6 build.
Modified: branches/7.5.x/pom.xml
===================================================================
--- branches/7.5.x/pom.xml 2014-11-18 23:01:52 UTC (rev 2547)
+++ branches/7.5.x/pom.xml 2014-11-18 23:08:09 UTC (rev 2548)
@@ -33,7 +33,7 @@
<groupId>org.jboss.web</groupId>
<artifactId>jbossweb</artifactId>
- <version>7.5.0.Beta5</version>
+ <version>7.5.0.Beta6</version>
<name>JBoss Web</name>
<description>Servlet 3.0 container</description>
10 years, 1 month
JBossWeb SVN: r2547 - branches/7.5.x/src/main/java/org/apache/coyote/http11.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-18 18:01:52 -0500 (Tue, 18 Nov 2014)
New Revision: 2547
Modified:
branches/7.5.x/src/main/java/org/apache/coyote/http11/InternalNioInputBuffer.java
Log:
Revert r2538 except leave all the plumbing and the sync cleanup.
Modified: branches/7.5.x/src/main/java/org/apache/coyote/http11/InternalNioInputBuffer.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/coyote/http11/InternalNioInputBuffer.java 2014-11-18 22:10:32 UTC (rev 2546)
+++ branches/7.5.x/src/main/java/org/apache/coyote/http11/InternalNioInputBuffer.java 2014-11-18 23:01:52 UTC (rev 2547)
@@ -146,11 +146,11 @@
}
if (notify) {
- if (listener == null) {
+ //if (listener == null) {
if (!endpoint.processChannel(attachment, SocketStatus.OPEN_READ)) {
endpoint.closeChannel(attachment);
}
- } else {
+ /*} else {
Thread thread = Thread.currentThread();
ClassLoader originalClassLoader = thread.getContextClassLoader();
try {
@@ -167,7 +167,7 @@
} finally {
thread.setContextClassLoader(originalClassLoader);
}
- }
+ }*/
}
}
10 years, 1 month
JBossWeb SVN: r2546 - branches/7.5.x/src/main/java/org/apache/tomcat/util/net.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-18 17:10:32 -0500 (Tue, 18 Nov 2014)
New Revision: 2546
Modified:
branches/7.5.x/src/main/java/org/apache/tomcat/util/net/NioEndpoint.java
Log:
BZ1119147: Patch submitted by Dominik Pospisil.
Modified: branches/7.5.x/src/main/java/org/apache/tomcat/util/net/NioEndpoint.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/tomcat/util/net/NioEndpoint.java 2014-11-18 17:31:39 UTC (rev 2545)
+++ branches/7.5.x/src/main/java/org/apache/tomcat/util/net/NioEndpoint.java 2014-11-18 22:10:32 UTC (rev 2546)
@@ -28,6 +28,9 @@
import java.nio.channels.CompletionHandler;
import java.nio.channels.WritePendingException;
import java.nio.file.StandardOpenOption;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
@@ -42,6 +45,7 @@
import org.apache.tomcat.util.net.NioEndpoint.Handler.SocketState;
import org.apache.tomcat.util.net.jsse.NioJSSESocketChannelFactory;
import org.jboss.web.CoyoteLogger;
+import sun.security.util.SecurityConstants;
/**
* {@code NioEndpoint} NIO2 endpoint, providing the following services:
@@ -1190,6 +1194,9 @@
private final String namePrefix;
private final int threadPriority;
+ private final AccessControlContext acc;
+ private final ClassLoader ccl;
+
/**
* Create a new instance of {@code DefaultThreadFactory}
*
@@ -1201,7 +1208,20 @@
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
this.namePrefix = namePrefix;
this.threadPriority = threadPriority;
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ // Calls to getContextClassLoader from this class
+ // never trigger a security check, but we check
+ // whether our callers have this permission anyways.
+ sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
+
+ // Fail fast
+ sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
+ this.acc = AccessController.getContext();
+ this.ccl = Thread.currentThread().getContextClassLoader();
+ }
/**
*
@@ -1216,16 +1236,32 @@
/**
* Create and return a new thread
*/
- public Thread newThread(Runnable r) {
- Thread thread = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
- if (thread.isDaemon())
+ public Thread newThread(final Runnable r) {
+ return AccessController.doPrivileged(new PrivilegedAction<Thread>() {
+
+ @Override
+ public Thread run() {
+ Thread thread = new Thread(group, new Runnable() {
+
+ @Override
+ public void run() {
+ Thread.currentThread().setContextClassLoader(ccl);
+ r.run();
+ }
+ }, namePrefix + threadNumber.getAndIncrement(), 0);
+ if (thread.isDaemon()) {
thread.setDaemon(false);
+ }
- if (thread.getPriority() != this.threadPriority)
- thread.setPriority(this.threadPriority);
+ if (thread.getPriority() != threadPriority) {
+ thread.setPriority(threadPriority);
+ }
return thread;
}
+ }, acc);
+
}
+ }
/**
* SendfileData class.
10 years, 1 month
JBossWeb SVN: r2545 - branches/7.5.x/src/main/java/org/apache/catalina/valves.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-18 12:31:39 -0500 (Tue, 18 Nov 2014)
New Revision: 2545
Modified:
branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java
Log:
BZ1163126 refix: The inner class used was not actually serializable (additional stuff).
Modified: branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java 2014-11-18 15:58:06 UTC (rev 2544)
+++ branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java 2014-11-18 17:31:39 UTC (rev 2545)
@@ -241,9 +241,9 @@
}
class CrawlerBindingListener implements HttpSessionBindingListener, Serializable {
- private static final long serialVersionUID = -3775762684177732270L;
- private final transient Map<String,String> clientIpSessionId;
- private final transient Map<String,String> sessionIdClientIp;
+ private static final long serialVersionUID = -8841692120840734349L;
+ private transient Map<String,String> clientIpSessionId;
+ private transient Map<String,String> sessionIdClientIp;
CrawlerBindingListener(Map<String,String> clientIpSessionId, Map<String,String> sessionIdClientIp) {
this.clientIpSessionId = clientIpSessionId;
@@ -257,9 +257,11 @@
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
- String clientIp = sessionIdClientIp.remove(event.getSession().getId());
- if (clientIp != null) {
- clientIpSessionId.remove(clientIp);
+ if (sessionIdClientIp != null) {
+ String clientIp = sessionIdClientIp.remove(event.getSession().getId());
+ if (clientIp != null) {
+ clientIpSessionId.remove(clientIp);
+ }
}
}
}
10 years, 1 month
JBossWeb SVN: r2544 - branches/7.5.x/src/main/java/org/apache/catalina/valves.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-18 10:58:06 -0500 (Tue, 18 Nov 2014)
New Revision: 2544
Modified:
branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java
Log:
BZ1163126 refix: The inner class used was not actually serializable.
Modified: branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java 2014-11-17 15:00:02 UTC (rev 2543)
+++ branches/7.5.x/src/main/java/org/apache/catalina/valves/CrawlerSessionManagerValve.java 2014-11-18 15:58:06 UTC (rev 2544)
@@ -220,7 +220,8 @@
clientIpSessionId.put(clientIp, s.getId());
sessionIdClientIp.put(s.getId(), clientIp);
// #valueUnbound() will be called on session expiration
- s.setAttribute(this.getClass().getName(), new CrawlerBindingListener());
+ s.setAttribute(this.getClass().getName(),
+ new CrawlerBindingListener(clientIpSessionId, sessionIdClientIp));
s.setMaxInactiveInterval(sessionInactiveInterval);
if (CatalinaLogger.VALVES_LOGGER.isDebugEnabled()) {
@@ -237,18 +238,28 @@
}
}
- protected class CrawlerBindingListener implements HttpSessionBindingListener, Serializable {
- private static final long serialVersionUID = -3775762684177732270L;
- @Override
- public void valueBound(HttpSessionBindingEvent event) {
- // NOOP
+}
+
+class CrawlerBindingListener implements HttpSessionBindingListener, Serializable {
+ private static final long serialVersionUID = -3775762684177732270L;
+ private final transient Map<String,String> clientIpSessionId;
+ private final transient Map<String,String> sessionIdClientIp;
+
+ CrawlerBindingListener(Map<String,String> clientIpSessionId, Map<String,String> sessionIdClientIp) {
+ this.clientIpSessionId = clientIpSessionId;
+ this.sessionIdClientIp = sessionIdClientIp;
+ }
+
+ @Override
+ public void valueBound(HttpSessionBindingEvent event) {
+ // NOOP
+ }
+
+ @Override
+ public void valueUnbound(HttpSessionBindingEvent event) {
+ String clientIp = sessionIdClientIp.remove(event.getSession().getId());
+ if (clientIp != null) {
+ clientIpSessionId.remove(clientIp);
}
- @Override
- public void valueUnbound(HttpSessionBindingEvent event) {
- String clientIp = sessionIdClientIp.remove(event.getSession().getId());
- if (clientIp != null) {
- clientIpSessionId.remove(clientIp);
- }
- }
}
}
10 years, 1 month
JBossWeb SVN: r2543 - tags.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-17 10:00:02 -0500 (Mon, 17 Nov 2014)
New Revision: 2543
Added:
tags/JBOSSWEB_7_5_0_BETA5/
Log:
Beta5 build.
10 years, 1 month
JBossWeb SVN: r2542 - branches/7.5.x.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-17 09:59:33 -0500 (Mon, 17 Nov 2014)
New Revision: 2542
Modified:
branches/7.5.x/pom.xml
Log:
Beta5 build.
Modified: branches/7.5.x/pom.xml
===================================================================
--- branches/7.5.x/pom.xml 2014-11-17 11:43:26 UTC (rev 2541)
+++ branches/7.5.x/pom.xml 2014-11-17 14:59:33 UTC (rev 2542)
@@ -33,7 +33,7 @@
<groupId>org.jboss.web</groupId>
<artifactId>jbossweb</artifactId>
- <version>7.5.0.Beta4</version>
+ <version>7.5.0.Beta5</version>
<name>JBoss Web</name>
<description>Servlet 3.0 container</description>
10 years, 1 month
JBossWeb SVN: r2541 - in branches/7.5.x/src/main/java/org/apache: tomcat/websocket/server and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2014-11-17 06:43:26 -0500 (Mon, 17 Nov 2014)
New Revision: 2541
Modified:
branches/7.5.x/src/main/java/org/apache/catalina/connector/OutputBuffer.java
branches/7.5.x/src/main/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java
Log:
Change websocket output to skip buffering and add some sync (input is synced upstream, but not output, which is weird).
Modified: branches/7.5.x/src/main/java/org/apache/catalina/connector/OutputBuffer.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/catalina/connector/OutputBuffer.java 2014-11-14 11:10:55 UTC (rev 2540)
+++ branches/7.5.x/src/main/java/org/apache/catalina/connector/OutputBuffer.java 2014-11-17 11:43:26 UTC (rev 2541)
@@ -336,6 +336,9 @@
*/
public void flush()
throws IOException {
+ if (response.getRequest().getUpgradeHandler() != null) {
+ return;
+ }
doFlush(true);
}
@@ -446,15 +449,31 @@
if (closed)
return;
- bb.append(b, off, len);
- bytesWritten += len;
+ if (response.getRequest().getUpgradeHandler() != null) {
+ // If we really have something to write
+ if (len > 0) {
+ // real write to the adapter
+ ByteChunk output = new ByteChunk();
+ output.setBytes(b, off, len);
+ try {
+ coyoteResponse.doWrite(output);
+ } catch (IOException e) {
+ // An IOException on a write is almost always due to
+ // the remote client aborting the request. Wrap this
+ // so that it can be handled better by the error dispatcher.
+ throw new ClientAbortException(e);
+ }
+ }
+ } else {
+ bb.append(b, off, len);
+ bytesWritten += len;
- // if called from within flush(), then immediately flush
- // remaining bytes
- if (doFlush) {
- bb.flushBuffer();
+ // if called from within flush(), then immediately flush
+ // remaining bytes
+ if (doFlush) {
+ bb.flushBuffer();
+ }
}
-
}
Modified: branches/7.5.x/src/main/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java
===================================================================
--- branches/7.5.x/src/main/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java 2014-11-14 11:10:55 UTC (rev 2540)
+++ branches/7.5.x/src/main/java/org/apache/tomcat/websocket/server/WsRemoteEndpointImplServer.java 2014-11-17 11:43:26 UTC (rev 2541)
@@ -47,6 +47,7 @@
private final ExecutorService executorService;
private volatile SendHandler handler = null;
private volatile ByteBuffer[] buffers = null;
+ private final Object connectionWriteLock = new Object();
private volatile long timeoutExpiry = -1;
private volatile boolean close;
@@ -77,53 +78,54 @@
public void onWritePossible(boolean useDispatch) {
- if (buffers == null) {
- // Servlet 3.1 will call the write listener once even if nothing
- // was written
- return;
- }
- boolean complete = true;
- try {
- // If this is false there will be a call back when it is true
- while (sos.isReady()) {
- complete = true;
- for (ByteBuffer buffer : buffers) {
- // FIXME: might not be needed
- synchronized (buffer) {
- if (buffer.hasRemaining()) {
- complete = false;
- sos.write(buffer.array(), buffer.arrayOffset(),
- buffer.limit());
- buffer.position(buffer.limit());
- break;
+ synchronized (connectionWriteLock) {
+ if (buffers == null) {
+ // Servlet 3.1 will call the write listener once even if nothing
+ // was written
+ return;
+ }
+ boolean complete = true;
+ try {
+ // If this is false there will be a call back when it is true
+ while (sos.isReady()) {
+ complete = true;
+ for (ByteBuffer buffer : buffers) {
+ synchronized (buffer) {
+ if (buffer.hasRemaining()) {
+ complete = false;
+ sos.write(buffer.array(), buffer.arrayOffset(),
+ buffer.limit());
+ buffer.position(buffer.limit());
+ break;
+ }
}
}
- }
- if (complete) {
- wsWriteTimeout.unregister(this);
- clearHandler(null, useDispatch);
- // Explicit flush for compatibility with buffered streams
- sos.flush();
- if (close) {
- close();
+ if (complete) {
+ wsWriteTimeout.unregister(this);
+ clearHandler(null, useDispatch);
+ // Explicit flush for compatibility with buffered streams
+ sos.flush();
+ if (close) {
+ close();
+ }
+ break;
}
- break;
}
+
+ } catch (IOException ioe) {
+ wsWriteTimeout.unregister(this);
+ clearHandler(ioe, useDispatch);
+ close();
}
+ if (!complete) {
+ // Async write is in progress
- } catch (IOException ioe) {
- wsWriteTimeout.unregister(this);
- clearHandler(ioe, useDispatch);
- close();
- }
- if (!complete) {
- // Async write is in progress
-
- long timeout = getSendTimeout();
- if (timeout > 0) {
- // Register with timeout thread
- timeoutExpiry = timeout + System.currentTimeMillis();
- wsWriteTimeout.register(this);
+ long timeout = getSendTimeout();
+ if (timeout > 0) {
+ // Register with timeout thread
+ timeoutExpiry = timeout + System.currentTimeMillis();
+ wsWriteTimeout.register(this);
+ }
}
}
}
10 years, 1 month