SOLR-18175: close request in PeerSync (#4950)
diff --git a/solr/core/src/java/org/apache/solr/update/PeerSync.java b/solr/core/src/java/org/apache/solr/update/PeerSync.java
index 2552b89..8476dc8 100644
--- a/solr/core/src/java/org/apache/solr/update/PeerSync.java
+++ b/solr/core/src/java/org/apache/solr/update/PeerSync.java
@@ -755,6 +755,7 @@
           throw e;
         } finally {
           IOUtils.closeQuietly(proc);
+          req.close();
         }
       }
     }
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
index ac460da..1841a01 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrQueryParser.java
@@ -1734,175 +1734,179 @@
 
   @Test
   public void testFieldExistsQueries() throws SyntaxError {
-    SolrQueryRequest req = req();
-    String[] fieldSuffix =
-        new String[] {
-          "ti",
-          "tf",
-          "td",
-          "tl",
-          "tdt", // trie types
-          "pi",
-          "pf",
-          "pd",
-          "pl",
-          "pdt", // point types
-          "i",
-          "f",
-          "d",
-          "l",
-          "dt",
-          "s",
-          "b", // numeric types
-          "is",
-          "fs",
-          "ds",
-          "ls",
-          "dts",
-          "ss",
-          "bs", // multi-valued
-          "i_dv",
-          "f_dv",
-          "d_dv",
-          "l_dv",
-          "dt_dv",
-          "s_dv",
-          "b_dv", // numerics + docValues
-          "is_dv",
-          "fs_dv",
-          "ds_dv",
-          "ls_dv",
-          "dts_dv",
-          "ss_dv",
-          "bs_dv", // multi-docValues
-          "i_dvo",
-          "f_dvo",
-          "d_dvo",
-          "l_dvo",
-          "dt_dvo", // not indexed
-          "t",
-          "t_on",
-          "b_norms",
-          "s_norms",
-          "dt_norms",
-          "i_norms",
-          "l_norms",
-          "f_norms",
-          "d_norms"
-        };
-    String[] existenceQueries = new String[] {"*", "[* TO *]"};
+    try (SolrQueryRequest req = req()) {
+      String[] fieldSuffix =
+          new String[] {
+            "ti",
+            "tf",
+            "td",
+            "tl",
+            "tdt", // trie types
+            "pi",
+            "pf",
+            "pd",
+            "pl",
+            "pdt", // point types
+            "i",
+            "f",
+            "d",
+            "l",
+            "dt",
+            "s",
+            "b", // numeric types
+            "is",
+            "fs",
+            "ds",
+            "ls",
+            "dts",
+            "ss",
+            "bs", // multi-valued
+            "i_dv",
+            "f_dv",
+            "d_dv",
+            "l_dv",
+            "dt_dv",
+            "s_dv",
+            "b_dv", // numerics + docValues
+            "is_dv",
+            "fs_dv",
+            "ds_dv",
+            "ls_dv",
+            "dts_dv",
+            "ss_dv",
+            "bs_dv", // multi-docValues
+            "i_dvo",
+            "f_dvo",
+            "d_dvo",
+            "l_dvo",
+            "dt_dvo", // not indexed
+            "t",
+            "t_on",
+            "b_norms",
+            "s_norms",
+            "dt_norms",
+            "i_norms",
+            "l_norms",
+            "f_norms",
+            "d_norms"
+          };
+      String[] existenceQueries = new String[] {"*", "[* TO *]"};
 
-    for (String existenceQuery : existenceQueries) {
-      for (String suffix : fieldSuffix) {
-        IndexSchema indexSchema = h.getCore().getLatestSchema();
-        String field = "foo_" + suffix;
-        String query = field + ":" + existenceQuery;
-        QParser qParser = QParser.getParser(query, req);
-        Query createdQuery = qParser.getQuery();
-        SchemaField schemaField = indexSchema.getField(field);
+      for (String existenceQuery : existenceQueries) {
+        for (String suffix : fieldSuffix) {
+          IndexSchema indexSchema = h.getCore().getLatestSchema();
+          String field = "foo_" + suffix;
+          String query = field + ":" + existenceQuery;
+          QParser qParser = QParser.getParser(query, req);
+          Query createdQuery = qParser.getQuery();
+          SchemaField schemaField = indexSchema.getField(field);
 
-        // Test float & double realNumber queries differently
-        if ("[* TO *]".equals(existenceQuery)
-            && (schemaField.getType().getNumberType() == NumberType.DOUBLE
-                || schemaField.getType().getNumberType() == NumberType.FLOAT)) {
-          assertFalse(
-              "For float and double fields \""
-                  + query
-                  + "\" is not an existence query, so the query returned should not be a FieldExistsQuery.",
-              createdQuery instanceof FieldExistsQuery);
-          assertFalse(
-              "For float and double fields \""
-                  + query
-                  + "\" is not an existence query, so the query returned should not be a FieldExistsQuery.",
-              createdQuery instanceof FieldExistsQuery);
-          assertFalse(
-              "For float and double fields \""
-                  + query
-                  + "\" is not an existence query, so NaN should not be matched via a ConstantScoreQuery.",
-              createdQuery instanceof ConstantScoreQuery);
-          assertFalse(
-              "For float and double fields\""
-                  + query
-                  + "\" is not an existence query, so NaN should not be matched via a BooleanQuery (NaN and [* TO *]).",
-              createdQuery instanceof BooleanQuery);
-        } else {
-          if (schemaField.hasDocValues()) {
-            assertTrue(
-                "Field has docValues, so existence query \""
+          // Test float & double realNumber queries differently
+          if ("[* TO *]".equals(existenceQuery)
+              && (schemaField.getType().getNumberType() == NumberType.DOUBLE
+                  || schemaField.getType().getNumberType() == NumberType.FLOAT)) {
+            assertFalse(
+                "For float and double fields \""
                     + query
-                    + "\" should return FieldExistsQuery",
+                    + "\" is not an existence query, so the query returned should not be a FieldExistsQuery.",
                 createdQuery instanceof FieldExistsQuery);
-          } else if (!schemaField.omitNorms()
-              && !schemaField
-                  .getType()
-                  .isPointField()) { // TODO: Remove !isPointField() for SOLR-14199
-            assertTrue(
-                "Field has norms and no docValues, so existence query \""
+            assertFalse(
+                "For float and double fields \""
                     + query
-                    + "\" should return FieldExistsQuery",
+                    + "\" is not an existence query, so the query returned should not be a FieldExistsQuery.",
                 createdQuery instanceof FieldExistsQuery);
-          } else if (schemaField.getType().getNumberType() == NumberType.DOUBLE
-              || schemaField.getType().getNumberType() == NumberType.FLOAT) {
-            if (schemaField.getType().isPointField()) {
+            assertFalse(
+                "For float and double fields \""
+                    + query
+                    + "\" is not an existence query, so NaN should not be matched via a ConstantScoreQuery.",
+                createdQuery instanceof ConstantScoreQuery);
+            assertFalse(
+                "For float and double fields\""
+                    + query
+                    + "\" is not an existence query, so NaN should not be matched via a BooleanQuery (NaN and [* TO *]).",
+                createdQuery instanceof BooleanQuery);
+          } else {
+            if (schemaField.hasDocValues()) {
               assertTrue(
-                  "PointField with NaN values must do a range query with an upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have norms or docValues: \""
+                  "Field has docValues, so existence query \""
                       + query
-                      + "\".",
-                  createdQuery instanceof PointRangeQuery);
-              if (schemaField.getType().getNumberType() == NumberType.DOUBLE) {
-                assertEquals(
+                      + "\" should return FieldExistsQuery",
+                  createdQuery instanceof FieldExistsQuery);
+            } else if (!schemaField.omitNorms()
+                && !schemaField
+                    .getType()
+                    .isPointField()) { // TODO: Remove !isPointField() for SOLR-14199
+              assertTrue(
+                  "Field has norms and no docValues, so existence query \""
+                      + query
+                      + "\" should return FieldExistsQuery",
+                  createdQuery instanceof FieldExistsQuery);
+            } else if (schemaField.getType().getNumberType() == NumberType.DOUBLE
+                || schemaField.getType().getNumberType() == NumberType.FLOAT) {
+              if (schemaField.getType().isPointField()) {
+                assertTrue(
                     "PointField with NaN values must do a range query with an upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have norms or docValues: \""
                         + query
                         + "\".",
-                    Double.NaN,
-                    DoublePoint.decodeDimension(
-                        ((PointRangeQuery) createdQuery).getUpperPoint(), 0),
-                    0);
+                    createdQuery instanceof PointRangeQuery);
+                if (schemaField.getType().getNumberType() == NumberType.DOUBLE) {
+                  assertEquals(
+                      "PointField with NaN values must do a range query with an upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have norms or docValues: \""
+                          + query
+                          + "\".",
+                      Double.NaN,
+                      DoublePoint.decodeDimension(
+                          ((PointRangeQuery) createdQuery).getUpperPoint(), 0),
+                      0);
+                } else {
+                  assertEquals(
+                      "PointField with NaN values must do a range query with an upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have norms or docValues: \""
+                          + query
+                          + "\".",
+                      Float.NaN,
+                      FloatPoint.decodeDimension(
+                          ((PointRangeQuery) createdQuery).getUpperPoint(), 0),
+                      0);
+                }
               } else {
-                assertEquals(
-                    "PointField with NaN values must do a range query with an upper bound of NaN (Sorted higher than +Infinity) if the field doesn't have norms or docValues: \""
+                assertTrue(
+                    "PointField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
                         + query
                         + "\".",
-                    Float.NaN,
-                    FloatPoint.decodeDimension(((PointRangeQuery) createdQuery).getUpperPoint(), 0),
-                    0);
+                    createdQuery instanceof ConstantScoreQuery);
+                assertTrue(
+                    "NumericField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
+                        + query
+                        + "\".",
+                    ((ConstantScoreQuery) createdQuery).getQuery() instanceof BooleanQuery);
+                assertEquals(
+                    "NumericField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
+                        + query
+                        + "\". This boolean query must be an OR.",
+                    1,
+                    ((BooleanQuery) ((ConstantScoreQuery) createdQuery).getQuery())
+                        .getMinimumNumberShouldMatch());
+                assertEquals(
+                    "NumericField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
+                        + query
+                        + "\". This boolean query must have 2 clauses.",
+                    2,
+                    ((BooleanQuery) ((ConstantScoreQuery) createdQuery).getQuery())
+                        .clauses()
+                        .size());
               }
             } else {
-              assertTrue(
-                  "PointField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
+              assertFalse(
+                  "Field doesn't have docValues, so existence query \""
                       + query
-                      + "\".",
-                  createdQuery instanceof ConstantScoreQuery);
-              assertTrue(
-                  "NumericField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
+                      + "\" should not return FieldExistsQuery",
+                  createdQuery instanceof FieldExistsQuery);
+              assertFalse(
+                  "Field doesn't have norms, so existence query \""
                       + query
-                      + "\".",
-                  ((ConstantScoreQuery) createdQuery).getQuery() instanceof BooleanQuery);
-              assertEquals(
-                  "NumericField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
-                      + query
-                      + "\". This boolean query must be an OR.",
-                  1,
-                  ((BooleanQuery) ((ConstantScoreQuery) createdQuery).getQuery())
-                      .getMinimumNumberShouldMatch());
-              assertEquals(
-                  "NumericField with NaN values must include \"exists or NaN\" if the field doesn't have norms or docValues: \""
-                      + query
-                      + "\". This boolean query must have 2 clauses.",
-                  2,
-                  ((BooleanQuery) ((ConstantScoreQuery) createdQuery).getQuery()).clauses().size());
+                      + "\" should not return FieldExistsQuery",
+                  createdQuery instanceof FieldExistsQuery);
             }
-          } else {
-            assertFalse(
-                "Field doesn't have docValues, so existence query \""
-                    + query
-                    + "\" should not return FieldExistsQuery",
-                createdQuery instanceof FieldExistsQuery);
-            assertFalse(
-                "Field doesn't have norms, so existence query \""
-                    + query
-                    + "\" should not return FieldExistsQuery",
-                createdQuery instanceof FieldExistsQuery);
           }
         }
       }