Author: remm
Date: Wed Jun 10 12:45:26 2015
New Revision: 1684663

URL: http://svn.apache.org/r1684663
Log:
Direct buffers need explicit cleanup to ensure complete reliability without 
OOMs.

Modified:
    tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
    tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
    tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
    tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java

Modified: tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/security/SecurityClassLoad.java Wed 
Jun 10 12:45:26 2015
@@ -263,6 +263,7 @@ public final class SecurityClassLoad {
             throws Exception {
         final String basePackage = "org.apache.tomcat.";
         // buf
+        loader.loadClass(basePackage + "util.buf.ByteBufferUtils");
         loader.loadClass(basePackage + "util.buf.HexUtils");
         loader.loadClass(basePackage + "util.buf.StringCache");
         loader.loadClass(basePackage + "util.buf.StringCache$ByteEntry");

Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/buf/ByteBufferUtils.java Wed Jun 
10 12:45:26 2015
@@ -16,10 +16,29 @@
  */
 package org.apache.tomcat.util.buf;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.nio.ByteBuffer;
 
 public class ByteBufferUtils {
 
+    private static final Method cleanerMethod;
+    private static final Method cleanMethod;
+
+    static {
+        try {
+            ByteBuffer tempBuffer = ByteBuffer.allocateDirect(0);
+            cleanerMethod = tempBuffer.getClass().getMethod("cleaner");
+            cleanerMethod.setAccessible(true);
+            Object cleanerObject = cleanerMethod.invoke(tempBuffer);
+            cleanMethod = cleanerObject.getClass().getMethod("clean");
+            cleanMethod.invoke(cleanerObject);
+        } catch (IllegalAccessException | IllegalArgumentException
+                | InvocationTargetException | NoSuchMethodException | 
SecurityException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
     private ByteBufferUtils() {
         // Hide the default constructor since this is a utility class.
     }
@@ -56,8 +75,10 @@ public class ByteBufferUtils {
         }
 
         ByteBuffer out;
+        boolean direct = false;
         if (in.isDirect()) {
             out = ByteBuffer.allocateDirect(newSize);
+            direct = true;
         } else {
             out = ByteBuffer.allocate(newSize);
         }
@@ -66,6 +87,20 @@ public class ByteBufferUtils {
         in.flip();
         out.put(in);
 
+        if (direct) {
+            cleanDirectBuffer(in);
+        }
+
         return out;
     }
+
+    public static void cleanDirectBuffer(ByteBuffer buf) {
+        try {
+            cleanMethod.invoke(cleanerMethod.invoke(buf));
+        } catch (IllegalAccessException | IllegalArgumentException
+                | InvocationTargetException | SecurityException e) {
+            // Ignore
+        }
+    }
+
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Wed Jun 10 
12:45:26 2015
@@ -51,6 +51,7 @@ import org.apache.tomcat.jni.Sockaddr;
 import org.apache.tomcat.jni.Socket;
 import org.apache.tomcat.jni.Status;
 import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.buf.ByteBufferUtils;
 import org.apache.tomcat.util.net.AbstractEndpoint.Acceptor.AcceptorState;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
 import org.apache.tomcat.util.net.SSLHostConfig.Type;
@@ -2569,6 +2570,9 @@ public class AprEndpoint extends Abstrac
                     return;
                 }
                 closed = true;
+                if (sslOutputBuffer != null) {
+                    ByteBufferUtils.cleanDirectBuffer(sslOutputBuffer);
+                }
                 ((AprEndpoint) 
getEndpoint()).getPoller().close(getSocket().longValue());
             }
         }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Channel.java Wed Jun 10 
12:45:26 2015
@@ -55,6 +55,13 @@ public class Nio2Channel implements Asyn
         bufHandler.reset();
     }
 
+    /**
+     * Free the channel memory
+     */
+    public void free() {
+        bufHandler.free();
+    }
+
     public SocketWrapperBase<Nio2Channel> getSocket() {
         return socket;
     }

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/Nio2Endpoint.java Wed Jun 10 
12:45:26 2015
@@ -1660,7 +1660,9 @@ public class Nio2Endpoint extends Abstra
                             // Close socket and pool
                             closeSocket(socket);
                             if (running && !paused) {
-                                nioChannels.push(socket.getSocket());
+                                if (!nioChannels.push(socket.getSocket())) {
+                                    socket.getSocket().free();
+                                }
                             }
                         } else if (state == Handler.SocketState.LONG) {
                             if (socket.isAsync()) {
@@ -1673,7 +1675,9 @@ public class Nio2Endpoint extends Abstra
                     } else if (handshake == -1 ) {
                         closeSocket(socket);
                         if (running && !paused) {
-                            nioChannels.push(socket.getSocket());
+                            if (!nioChannels.push(socket.getSocket())) {
+                                socket.getSocket().free();
+                            }
                         }
                     }
                 } catch (VirtualMachineError vme) {

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioChannel.java Wed Jun 10 
12:45:26 2015
@@ -66,6 +66,13 @@ public class NioChannel implements ByteC
 
 
     /**
+     * Free the channel memory
+     */
+    public void free() {
+        bufHandler.free();
+    }
+
+    /**
      * Returns true if the network buffer has been flushed out and is empty.
      *
      * @param block     Unused. May be used when overridden

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Wed Jun 10 
12:45:26 2015
@@ -1536,7 +1536,9 @@ public class NioEndpoint extends Abstrac
                                     // We do NOT want to do this more than 
once - see BZ
                                     // 57340.
                                     if (running && !paused) {
-                                        nioChannels.push(socket);
+                                        if (!nioChannels.push(socket)) {
+                                            socket.free();
+                                        }
                                     }
                                     socket = null;
                                 }
@@ -1550,7 +1552,9 @@ public class NioEndpoint extends Abstrac
                             socket.getPoller().cancelledKey(key);
                         }
                         if (running && !paused) {
-                            nioChannels.push(socket);
+                            if (!nioChannels.push(socket)) {
+                                socket.free();
+                            }
                         }
                         socket = null;
                         ka = null;

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNio2Channel.java Wed Jun 
10 12:45:26 2015
@@ -122,6 +122,14 @@ public class SecureNio2Channel extends N
         closing = false;
     }
 
+    @Override
+    public void free() {
+        super.free();
+        if (endpoint.getSocketProperties().getDirectSslBuffer()) {
+            ByteBufferUtils.cleanDirectBuffer(netInBuffer);
+            ByteBufferUtils.cleanDirectBuffer(netOutBuffer);
+        }
+    }
 
     private class FutureFlush implements Future<Boolean> {
         private Future<Integer> integer;

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SecureNioChannel.java Wed Jun 
10 12:45:26 2015
@@ -93,6 +93,14 @@ public class SecureNioChannel extends Ni
         netInBuffer.clear();
     }
 
+    @Override
+    public void free() {
+        super.free();
+        if (endpoint.getSocketProperties().getDirectSslBuffer()) {
+            ByteBufferUtils.cleanDirectBuffer(netInBuffer);
+            ByteBufferUtils.cleanDirectBuffer(netOutBuffer);
+        }
+    }
 
 
//===========================================================================================
 //                  NIO SSL METHODS

Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java?rev=1684663&r1=1684662&r2=1684663&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java 
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketBufferHandler.java Wed 
Jun 10 12:45:26 2015
@@ -28,9 +28,11 @@ public class SocketBufferHandler {
     private volatile boolean writeBufferConfiguredForWrite = true;
     private volatile ByteBuffer writeBuffer;
 
+    private final boolean direct;
 
     public SocketBufferHandler(int readBufferSize, int writeBufferSize,
             boolean direct) {
+        this.direct = direct;
         if (direct) {
             readBuffer = ByteBuffer.allocateDirect(readBufferSize);
             writeBuffer = ByteBuffer.allocateDirect(writeBufferSize);
@@ -156,4 +158,12 @@ public class SocketBufferHandler {
         configureWriteBufferForWrite();
         writeBuffer = ByteBufferUtils.expand(writeBuffer, newSize);
     }
+
+    public void free() {
+        if (direct) {
+            ByteBufferUtils.cleanDirectBuffer(readBuffer);
+            ByteBufferUtils.cleanDirectBuffer(writeBuffer);
+        }
+    }
+
 }



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

Reply via email to