lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a.@apache.org
Subject [36/50] [abbrv] lucene-solr:jira/solr-11779: SOLR-12290: Do not close any servlet streams and improve our servlet stream closing prevention code for users and devs.
Date Tue, 08 May 2018 21:15:22 GMT
SOLR-12290: Do not close any servlet streams and improve our servlet stream closing prevention
code for users and devs.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/29620105
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/29620105
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/29620105

Branch: refs/heads/jira/solr-11779
Commit: 296201055f24f01e1610f2fb87aba7fa90b9dda1
Parents: ad0ad2e
Author: Mark Miller <markrmiller@apache.org>
Authored: Fri May 4 18:02:06 2018 -0500
Committer: Mark Miller <markrmiller@apache.org>
Committed: Fri May 4 18:02:06 2018 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   3 +
 .../org/apache/solr/handler/BlobHandler.java    |   6 +-
 .../apache/solr/handler/ReplicationHandler.java |   6 +-
 .../solr/handler/loader/CSVLoaderBase.java      |  75 +++++-----
 .../solr/handler/loader/JavabinLoader.java      |  16 +--
 .../org/apache/solr/servlet/HttpSolrCall.java   |   6 +-
 .../apache/solr/servlet/LoadAdminUiServlet.java |  14 +-
 .../solr/servlet/ServletInputStreamWrapper.java |   2 +-
 .../servlet/ServletOutputStreamWrapper.java     |   2 +-
 .../apache/solr/servlet/SolrDispatchFilter.java | 139 ++++++++++++-------
 .../apache/solr/servlet/SolrRequestParsers.java |   6 +-
 11 files changed, 147 insertions(+), 128 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index d4c2097..f74e2fd 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -206,6 +206,9 @@ Bug Fixes
 
 * SOLR-12202: Fix errors in solr-exporter.cmd. (Minoru Osuka via koji)
 
+* SOLR-12290: Do not close any servlet streams and improve our servlet stream closing prevention
code for users
+  and devs. (Mark Miller)
+
 Optimizations
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/handler/BlobHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/BlobHandler.java b/solr/core/src/java/org/apache/solr/handler/BlobHandler.java
index 30301c0..a998657 100644
--- a/solr/core/src/java/org/apache/solr/handler/BlobHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/BlobHandler.java
@@ -17,7 +17,6 @@
 package org.apache.solr.handler;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.invoke.MethodHandles;
 import java.math.BigInteger;
@@ -109,9 +108,8 @@ public class BlobHandler extends RequestHandlerBase implements PluginInfoInitial
 
       for (ContentStream stream : req.getContentStreams()) {
         ByteBuffer payload;
-        try (InputStream is = stream.getStream()) {
-          payload = SimplePostTool.inputStreamToByteArray(is, maxSize);
-        }
+        payload = SimplePostTool.inputStreamToByteArray(stream.getStream(), maxSize);
+        
         MessageDigest m = MessageDigest.getInstance("MD5");
         m.update(payload.array(), payload.position(), payload.limit());
         String md5 = new BigInteger(1, m.digest()).toString(16);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
index 1707c80..6afb8a0 100644
--- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
@@ -56,6 +56,7 @@ import java.util.zip.Checksum;
 import java.util.zip.DeflaterOutputStream;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.CloseShieldOutputStream;
 import org.apache.lucene.codecs.CodecUtil;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexCommit;
@@ -1515,6 +1516,7 @@ public class ReplicationHandler extends RequestHandlerBase implements
SolrCoreAw
     }
 
     protected void createOutputStream(OutputStream out) {
+      out = new CloseShieldOutputStream(out); // DeflaterOutputStream requires a close call,
but don't close the request outputstream
       if (Boolean.parseBoolean(compress)) {
         fos = new FastOutputStream(new DeflaterOutputStream(out));
       } else {
@@ -1579,7 +1581,7 @@ public class ReplicationHandler extends RequestHandlerBase implements
SolrCoreAw
           }
           if (read != buf.length) {
             writeNothingAndFlush();
-            fos.close();
+            fos.close(); // we close because DeflaterOutputStream requires a close call,
but but the request outputstream is protected
             break;
           }
           offset += read;
@@ -1638,7 +1640,7 @@ public class ReplicationHandler extends RequestHandlerBase implements
SolrCoreAw
             long bytesRead = channel.read(bb);
             if (bytesRead <= 0) {
               writeNothingAndFlush();
-              fos.close();
+              fos.close(); // we close because DeflaterOutputStream requires a close call,
but but the request outputstream is protected
               break;
             }
             fos.writeInt((int) bytesRead);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/handler/loader/CSVLoaderBase.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/loader/CSVLoaderBase.java b/solr/core/src/java/org/apache/solr/handler/loader/CSVLoaderBase.java
index b503fa3..fd8935d 100644
--- a/solr/core/src/java/org/apache/solr/handler/loader/CSVLoaderBase.java
+++ b/solr/core/src/java/org/apache/solr/handler/loader/CSVLoaderBase.java
@@ -28,7 +28,6 @@ import org.apache.solr.update.*;
 import org.apache.solr.update.processor.UpdateRequestProcessor;
 import org.apache.solr.internal.csv.CSVStrategy;
 import org.apache.solr.internal.csv.CSVParser;
-import org.apache.commons.io.IOUtils;
 
 import java.util.regex.Pattern;
 import java.util.List;
@@ -315,54 +314,48 @@ abstract class CSVLoaderBase extends ContentStreamLoader {
 
   /** load the CSV input */
   @Override
-  public void load(SolrQueryRequest req, SolrQueryResponse rsp, ContentStream stream, UpdateRequestProcessor
processor) throws IOException {
+  public void load(SolrQueryRequest req, SolrQueryResponse rsp, ContentStream stream, UpdateRequestProcessor
processor)
+      throws IOException {
     errHeader = "CSVLoader: input=" + stream.getSourceInfo();
-    Reader reader = null;
-    try {
-      reader = stream.getReader();
-      if (skipLines>0) {
-        if (!(reader instanceof BufferedReader)) {
-          reader = new BufferedReader(reader);
-        }
-        BufferedReader r = (BufferedReader)reader;
-        for (int i=0; i<skipLines; i++) {
-          r.readLine();
-        }
+    Reader reader = stream.getReader();
+    if (skipLines > 0) {
+      if (!(reader instanceof BufferedReader)) {
+        reader = new BufferedReader(reader);
       }
-
-      CSVParser parser = new CSVParser(reader, strategy);
-
-      // parse the fieldnames from the header of the file
-      if (fieldnames==null) {
-        fieldnames = parser.getLine();
-        if (fieldnames==null) {
-          throw new SolrException( SolrException.ErrorCode.BAD_REQUEST,"Expected fieldnames
in CSV input");
-        }
-        prepareFields();
+      BufferedReader r = (BufferedReader) reader;
+      for (int i = 0; i < skipLines; i++) {
+        r.readLine();
       }
+    }
 
-      // read the rest of the CSV file
-      for(;;) {
-        int line = parser.getLineNumber();  // for error reporting in MT mode
-        String[] vals = null;
-        try {
-          vals = parser.getLine();
-        } catch (IOException e) {
-          //Catch the exception and rethrow it with more line information
-         input_err("can't read line: " + line, null, line, e);
-        }
-        if (vals==null) break;
+    CSVParser parser = new CSVParser(reader, strategy);
 
-        if (vals.length != fieldnames.length) {
-          input_err("expected "+fieldnames.length+" values but got "+vals.length, vals, line);
-        }
+    // parse the fieldnames from the header of the file
+    if (fieldnames == null) {
+      fieldnames = parser.getLine();
+      if (fieldnames == null) {
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Expected fieldnames
in CSV input");
+      }
+      prepareFields();
+    }
 
-        addDoc(line,vals);
+    // read the rest of the CSV file
+    for (;;) {
+      int line = parser.getLineNumber(); // for error reporting in MT mode
+      String[] vals = null;
+      try {
+        vals = parser.getLine();
+      } catch (IOException e) {
+        // Catch the exception and rethrow it with more line information
+        input_err("can't read line: " + line, null, line, e);
       }
-    } finally{
-      if (reader != null) {
-        IOUtils.closeQuietly(reader);
+      if (vals == null) break;
+
+      if (vals.length != fieldnames.length) {
+        input_err("expected " + fieldnames.length + " values but got " + vals.length, vals,
line);
       }
+
+      addDoc(line, vals);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java b/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
index f502a8e..aca3df4 100644
--- a/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
+++ b/solr/core/src/java/org/apache/solr/handler/loader/JavabinLoader.java
@@ -48,20 +48,8 @@ import org.apache.solr.update.processor.UpdateRequestProcessor;
 public class JavabinLoader extends ContentStreamLoader {
 
   @Override
-  public void load(SolrQueryRequest req, SolrQueryResponse rsp, ContentStream stream, UpdateRequestProcessor
processor) throws Exception {
-    InputStream is = null;
-    try {
-      is = stream.getStream();
-      parseAndLoadDocs(req, rsp, is, processor);
-    } finally {
-      if(is != null) {
-        is.close();
-      }
-    }
-  }
-  
-  private void parseAndLoadDocs(final SolrQueryRequest req, SolrQueryResponse rsp, InputStream
stream,
-                                final UpdateRequestProcessor processor) throws IOException
{
+  public void load(SolrQueryRequest req, SolrQueryResponse rsp, ContentStream cs, UpdateRequestProcessor
processor) throws Exception {
+    InputStream stream = cs.getStream();
     UpdateRequest update = null;
     JavaBinUpdateRequestCodec.StreamingUpdateHandler handler = new JavaBinUpdateRequestCodec.StreamingUpdateHandler()
{
       private AddUpdateCommand addCmd = null;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index 50fa71c..5e4dd78 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -39,8 +39,6 @@ import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.input.CloseShieldInputStream;
-import org.apache.commons.io.output.CloseShieldOutputStream;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.Header;
 import org.apache.http.HeaderIterator;
@@ -590,7 +588,7 @@ public class HttpSolrCall {
       } else if (isPostOrPutRequest) {
         HttpEntityEnclosingRequestBase entityRequest =
             "POST".equals(req.getMethod()) ? new HttpPost(urlstr) : new HttpPut(urlstr);
-        InputStream in = new CloseShieldInputStream(req.getInputStream()); // Prevent close
of container streams
+        InputStream in = req.getInputStream();
         HttpEntity entity = new InputStreamEntity(in, req.getContentLength());
         entityRequest.setEntity(entity);
         method = entityRequest;
@@ -785,7 +783,7 @@ public class HttpSolrCall {
       }
 
       if (Method.HEAD != reqMethod) {
-        OutputStream out = new CloseShieldOutputStream(response.getOutputStream()); // Prevent
close of container streams, see SOLR-8933
+        OutputStream out = response.getOutputStream();
         QueryResponseWriterUtil.writeQueryResponse(out, responseWriter, solrReq, solrRsp,
ct);
       }
       //else http HEAD request, nothing to write out, waited this long just to get ContentType

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java b/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
index c496ce1..1aa1137 100644
--- a/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
+++ b/solr/core/src/java/org/apache/solr/servlet/LoadAdminUiServlet.java
@@ -17,7 +17,6 @@
 package org.apache.solr.servlet;
 
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.CloseShieldOutputStream;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.solr.common.params.CommonParams;
@@ -41,10 +40,12 @@ import java.nio.charset.StandardCharsets;
 public final class LoadAdminUiServlet extends BaseSolrServlet {
 
   @Override
-  public void doGet(HttpServletRequest request,
-                    HttpServletResponse response)
+  public void doGet(HttpServletRequest _request,
+                    HttpServletResponse _response)
       throws IOException {
-
+    HttpServletRequest request = SolrDispatchFilter.closeShield(_request, false);
+    HttpServletResponse response = SolrDispatchFilter.closeShield(_response, false);
+    
     response.addHeader("X-Frame-Options", "DENY"); // security: SOLR-7966 - avoid clickjacking
for admin interface
 
     // This attribute is set by the SolrDispatchFilter
@@ -57,8 +58,8 @@ public final class LoadAdminUiServlet extends BaseSolrServlet {
         response.setCharacterEncoding("UTF-8");
         response.setContentType("text/html");
 
-        // Protect container owned streams from being closed by us, see SOLR-8933
-        out = new OutputStreamWriter(new CloseShieldOutputStream(response.getOutputStream()),
StandardCharsets.UTF_8);
+        // Don't close this! - see SOLR-8933
+        out = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8);
 
         String html = IOUtils.toString(in, "UTF-8");
         Package pack = SolrCore.class.getPackage();
@@ -77,7 +78,6 @@ public final class LoadAdminUiServlet extends BaseSolrServlet {
         out.write( StringUtils.replaceEach(html, search, replace) );
       } finally {
         IOUtils.closeQuietly(in);
-        IOUtils.closeQuietly(out);
       }
     } else {
       response.sendError(404);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/servlet/ServletInputStreamWrapper.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/ServletInputStreamWrapper.java b/solr/core/src/java/org/apache/solr/servlet/ServletInputStreamWrapper.java
index d229bf7..826dc59 100644
--- a/solr/core/src/java/org/apache/solr/servlet/ServletInputStreamWrapper.java
+++ b/solr/core/src/java/org/apache/solr/servlet/ServletInputStreamWrapper.java
@@ -32,7 +32,7 @@ import org.apache.solr.common.util.SuppressForbidden;
  */
 @SuppressForbidden(reason = "delegate methods")
 public class ServletInputStreamWrapper extends ServletInputStream {
-  final ServletInputStream stream;
+  ServletInputStream stream;
   
   public ServletInputStreamWrapper(ServletInputStream stream) throws IOException {
     this.stream = stream;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/servlet/ServletOutputStreamWrapper.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/ServletOutputStreamWrapper.java b/solr/core/src/java/org/apache/solr/servlet/ServletOutputStreamWrapper.java
index d12c3bd..1164146 100644
--- a/solr/core/src/java/org/apache/solr/servlet/ServletOutputStreamWrapper.java
+++ b/solr/core/src/java/org/apache/solr/servlet/ServletOutputStreamWrapper.java
@@ -32,7 +32,7 @@ import org.apache.solr.common.util.SuppressForbidden;
  */
 @SuppressForbidden(reason = "delegate methods")
 public class ServletOutputStreamWrapper extends ServletOutputStream {
-  final ServletOutputStream stream;
+  ServletOutputStream stream;
   
   public ServletOutputStreamWrapper(ServletOutputStream stream) {
     this.stream = stream;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
index fc0c28f..8f32a7d 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrDispatchFilter.java
@@ -37,20 +37,20 @@ import java.util.regex.Pattern;
 
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
+import javax.servlet.ReadListener;
 import javax.servlet.ServletException;
 import javax.servlet.ServletInputStream;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.UnavailableException;
+import javax.servlet.WriteListener;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponseWrapper;
 
 import org.apache.commons.io.FileCleaningTracker;
-import org.apache.commons.io.input.CloseShieldInputStream;
-import org.apache.commons.io.output.CloseShieldOutputStream;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.client.HttpClient;
 import org.apache.lucene.util.Version;
@@ -98,8 +98,6 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   protected HttpClient httpClient;
   private ArrayList<Pattern> excludePatterns;
   
-  // Effectively immutable
-  private Boolean testMode = null;
   private boolean isV2Enabled = !"true".equals(System.getProperty("disable.v2.api", "false"));
 
   private final String metricTag = Integer.toHexString(hashCode());
@@ -119,19 +117,6 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   }
   
   public SolrDispatchFilter() {
-    // turn on test mode when running tests
-    assert testMode = true;
-    
-    if (testMode == null) {
-      testMode = false;
-    } else {
-      String tm = System.getProperty("solr.tests.doContainerStreamCloseAssert");
-      if (tm != null) {
-        testMode = Boolean.parseBoolean(tm);
-      } else {
-        testMode = true;
-      }
-    }
   }
 
   public static final String PROPERTIES_ATTRIBUTE = "solr.properties";
@@ -341,8 +326,8 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   
   public void doFilter(ServletRequest _request, ServletResponse _response, FilterChain chain,
boolean retry) throws IOException, ServletException {
     if (!(_request instanceof HttpServletRequest)) return;
-    HttpServletRequest request = (HttpServletRequest)_request;
-    HttpServletResponse response = (HttpServletResponse)_response;
+    HttpServletRequest request = closeShield((HttpServletRequest)_request, retry);
+    HttpServletResponse response = closeShield((HttpServletResponse)_response, retry);
     
     try {
 
@@ -387,7 +372,7 @@ public class SolrDispatchFilter extends BaseSolrFilter {
         }
       }
 
-      HttpSolrCall call = getHttpSolrCall(closeShield(request, retry), closeShield(response,
retry), retry);
+      HttpSolrCall call = getHttpSolrCall(request, response, retry);
       ExecutorUtil.setServerThreadFlag(Boolean.TRUE);
       try {
         Action result = call.call();
@@ -486,31 +471,82 @@ public class SolrDispatchFilter extends BaseSolrFilter {
     return true;
   }
   
+  public static class ClosedServletInputStream extends ServletInputStream {
+    
+    public static final ClosedServletInputStream CLOSED_SERVLET_INPUT_STREAM = new ClosedServletInputStream();
+
+    @Override
+    public int read() {
+      return -1;
+    }
+
+    @Override
+    public boolean isFinished() {
+      return false;
+    }
+
+    @Override
+    public boolean isReady() {
+      return false;
+    }
+
+    @Override
+    public void setReadListener(ReadListener arg0) {}
+  }
+  
+  public static class ClosedServletOutputStream extends ServletOutputStream {
+    
+    public static final ClosedServletOutputStream CLOSED_SERVLET_OUTPUT_STREAM = new ClosedServletOutputStream();
+    
+    @Override
+    public void write(final int b) throws IOException {
+      throw new IOException("write(" + b + ") failed: stream is closed");
+    }
+    
+    @Override
+    public void flush() throws IOException {
+      throw new IOException("flush() failed: stream is closed");
+    }
+
+    @Override
+    public boolean isReady() {
+      return false;
+    }
+
+    @Override
+    public void setWriteListener(WriteListener arg0) {
+      throw new RuntimeException("setWriteListener() failed: stream is closed");
+    }
+  }
+
   /**
-   * Wrap the request's input stream with a close shield, as if by a {@link CloseShieldInputStream}.
If this is a
+   * Wrap the request's input stream with a close shield. If this is a
    * retry, we will assume that the stream has already been wrapped and do nothing.
    *
+   * Only the container should ever actually close the servlet output stream.
+   *
    * @param request The request to wrap.
    * @param retry If this is an original request or a retry.
    * @return A request object with an {@link InputStream} that will ignore calls to close.
    */
-  private HttpServletRequest closeShield(HttpServletRequest request, boolean retry) {
-    if (testMode && !retry) {
+  public static HttpServletRequest closeShield(HttpServletRequest request, boolean retry)
{
+    if (!retry) {
       return new HttpServletRequestWrapper(request) {
-        ServletInputStream stream;
-        
+
         @Override
         public ServletInputStream getInputStream() throws IOException {
-          // Lazy stream creation
-          if (stream == null) {
-            stream = new ServletInputStreamWrapper(super.getInputStream()) {
-              @Override
-              public void close() {
-                assert false : "Attempted close of request input stream.";
-              }
-            };
-          }
-          return stream;
+
+          return new ServletInputStreamWrapper(super.getInputStream()) {
+            @Override
+            public void close() {
+              // even though we skip closes, we let local tests know not to close so that
a full understanding can take
+              // place
+              assert Thread.currentThread().getStackTrace()[2].getClassName().matches(
+                  "org\\.apache\\.(?:solr|lucene).*") ? false : true : "Attempted close of
request input stream - never do this, you will spoil connection reuse and possibly disrupt
a client";
+              this.stream = ClosedServletInputStream.CLOSED_SERVLET_INPUT_STREAM;
+            }
+          };
+
         }
       };
     } else {
@@ -519,31 +555,34 @@ public class SolrDispatchFilter extends BaseSolrFilter {
   }
   
   /**
-   * Wrap the response's output stream with a close shield, as if by a {@link CloseShieldOutputStream}.
If this is a
+   * Wrap the response's output stream with a close shield. If this is a
    * retry, we will assume that the stream has already been wrapped and do nothing.
    *
+   * Only the container should ever actually close the servlet request stream.
+   *
    * @param response The response to wrap.
    * @param retry If this response corresponds to an original request or a retry.
    * @return A response object with an {@link OutputStream} that will ignore calls to close.
    */
-  private HttpServletResponse closeShield(HttpServletResponse response, boolean retry) {
-    if (testMode && !retry) {
+  public static HttpServletResponse closeShield(HttpServletResponse response, boolean retry)
{
+    if (!retry) {
       return new HttpServletResponseWrapper(response) {
-        ServletOutputStream stream;
-        
+
         @Override
         public ServletOutputStream getOutputStream() throws IOException {
-          // Lazy stream creation
-          if (stream == null) {
-            stream = new ServletOutputStreamWrapper(super.getOutputStream()) {
-              @Override
-              public void close() {
-                assert false : "Attempted close of response output stream.";
-              }
-            };
-          }
-          return stream;
+
+          return new ServletOutputStreamWrapper(super.getOutputStream()) {
+            @Override
+            public void close() {
+              // even though we skip closes, we let local tests know not to close so that
a full understanding can take
+              // place
+              assert Thread.currentThread().getStackTrace()[2].getClassName().matches(
+                  "org\\.apache\\.(?:solr|lucene).*") ? false : true : "Attempted close of
response output stream - never do this, you will spoil connection reuse and possibly disrupt
a client";
+              stream = ClosedServletOutputStream.CLOSED_SERVLET_OUTPUT_STREAM;
+            }
+          };
         }
+
       };
     } else {
       return response;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/29620105/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
index 60b6d2f..4bcb8d8 100644
--- a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
+++ b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java
@@ -519,8 +519,7 @@ public class SolrRequestParsers
 
     @Override
     public InputStream getStream() throws IOException {
-      // Protect container owned streams from being closed by us, see SOLR-8933
-      return new CloseShieldInputStream(req.getInputStream());
+      return req.getInputStream();
     }
   }
 
@@ -767,8 +766,7 @@ public class SolrRequestParsers
         String userAgent = req.getHeader("User-Agent");
         boolean isCurl = userAgent != null && userAgent.startsWith("curl/");
 
-        // Protect container owned streams from being closed by us, see SOLR-8933
-        FastInputStream input = FastInputStream.wrap( new CloseShieldInputStream(req.getInputStream())
);
+        FastInputStream input = FastInputStream.wrap(req.getInputStream());
 
         if (isCurl) {
           SolrParams params = autodetect(req, streams, input);


Mime
View raw message