1 /*
   2  * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6762191
  27  * @summary Setting stack size to 16K causes segmentation fault
  28  * @compile TooSmallStackSize.java
  29  * @run main TooSmallStackSize
  30  */
  31 
  32 /*
  33  * The primary purpose of this test is to make sure we can run with a 16k stack
  34  * size without crashing. Also this test will determine the minimum allowed
  35  * stack size for the platform (as provided by the JVM error message when a very
  36  * small stack is used), and then verify that the JVM can be launched with that stack
  37  * size without a crash or any error messages.
  38  *
  39  * Note: The '-Xss<size>' and '-XX:ThreadStackSize=<k-bytes>' options
  40  * both control Java thread stack size. This repo's version of the test
  41  * exercises the '-Xss' option. The hotspot repo's version of the test
  42  * exercises the '-XX:ThreadStackSize' VM option.
  43  */
  44 
  45 public class TooSmallStackSize extends TestHelper {
  46     /* for debugging. Normally false. */
  47     static final boolean verbose = false;
  48 
  49     static void printTestOutput(TestResult tr) {
  50         System.out.println("*** exitValue = " + tr.exitValue);
  51         for (String x : tr.testOutput) {
  52             System.out.println(x);
  53         }
  54     }
  55 
  56     /*
  57      * Returns the minimum stack size this platform will allowed based on the
  58      * contents of the error message the JVM outputs when too small of a
  59      * -Xss size was used.
  60      *
  61      * The TestResult argument must contain the result of having already run
  62      * the JVM with too small of a stack size.
  63      */
  64     static String getMinStackAllowed(TestResult tr) {
  65         /*
  66          * The JVM output will contain in one of the lines:
  67          *   "The Java thread stack size specified is too small. Specify at least 100k"
  68          * Although the actual size will vary. We need to extract this size
  69          * string from the output and return it.
  70          */
  71         String matchStr = "Specify at least ";
  72         for (String x : tr.testOutput) {
  73             int match_idx = x.indexOf(matchStr);
  74             if (match_idx >= 0) {
  75                 int size_start_idx = match_idx + matchStr.length();
  76                 int k_start_idx = x.indexOf("k", size_start_idx);
  77                 return x.substring(size_start_idx, k_start_idx + 1); // include the "k"
  78             }
  79         }
  80 
  81         System.out.println("Expect='" + matchStr + "'");
  82         System.out.println("Actual:");
  83         printTestOutput(tr);
  84         System.out.println("FAILED: Could not get the stack size from the output");
  85         throw new RuntimeException("test fails");
  86     }
  87 
  88     /*
  89      * Run the JVM with the specified stack size.
  90      *
  91      * Returns the minimum allowed stack size gleaned from the error message,
  92      * if there is an error message. Otherwise returns the stack size passed in.
  93      */
  94     static String checkStack(String stackSize) {
  95         String min_stack_allowed;
  96 
  97         if (verbose)
  98             System.out.println("*** Testing " + stackSize);
  99         TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version");
 100         if (verbose)
 101             printTestOutput(tr);
 102 
 103         if (tr.isOK()) {
 104             System.out.println("PASSED: got no error message with stack size of " + stackSize);
 105             min_stack_allowed = stackSize;
 106         } else {
 107             String matchStr = "The Java thread stack size specified is too small";
 108             if (tr.contains(matchStr)) {
 109                 System.out.println("PASSED: got expected error message with stack size of " + stackSize);
 110                 min_stack_allowed = getMinStackAllowed(tr);
 111             } else {
 112                 // Likely a crash
 113                 System.out.println("Expect='" + matchStr + "'");
 114                 System.out.println("Actual:");
 115                 printTestOutput(tr);
 116                 System.out.println("FAILED: Did not get expected error message with stack size of " + stackSize);
 117                 throw new RuntimeException("test fails");
 118             }
 119         }
 120 
 121         return min_stack_allowed;
 122     }
 123 
 124     /*
 125      * Run the JVM with the minimum allowed stack size. This should always succeed.
 126      */
 127     static void checkMinStackAllowed(String stackSize) {
 128         if (verbose)
 129             System.out.println("*** Testing " + stackSize);
 130         TestResult tr = doExec(javaCmd, "-Xss" + stackSize, "-version");
 131         if (verbose)
 132             printTestOutput(tr);
 133 
 134         if (tr.isOK()) {
 135             System.out.println("PASSED: VM launched with minimum allowed stack size of " + stackSize);
 136         } else {
 137             // Likely a crash
 138             System.out.println("Test output:");
 139             printTestOutput(tr);
 140             System.out.println("FAILED: VM failed to launch with minimum allowed stack size of " + stackSize);
 141             throw new RuntimeException("test fails");
 142         }
 143     }
 144 
 145     public static void main(String... args) {
 146         /*
 147          * The result of a 16k stack size should be a quick exit with a complaint
 148          * that the stack size is too small. However, for some win32 builds, the
 149          * stack is always at least 64k, and this also sometimes is the minimum
 150          * allowed size, so we won't see an error in this case.
 151          *
 152          * This test case will also produce a crash on some platforms if the fix
 153          * for 6762191 is not yet in place.
 154          */
 155         checkStack("16k");
 156 
 157         /*
 158          * Try with a 64k stack size, which is the size that the launcher will
 159          * set to if you try setting to anything smaller. This should produce the same
 160          * result as setting to 16k if the fix for 6762191 is in place.
 161          */
 162         String min_stack_allowed = checkStack("64k");
 163 
 164         /*
 165          * Try again with a the minimum stack size that was given in the error message
 166          */
 167         checkMinStackAllowed(min_stack_allowed);
 168 
 169         /*
 170          * Try again with a size that is not OS page aligned. This is to help test that
 171          * asserts added for 8176768 are not triggered.
 172          */
 173         checkMinStackAllowed("513k");
 174 
 175         /*
 176          * Try with 0k which indicates that the default thread stack size either from JVM or system
 177          * will be used, this should always succeed. It can verify the issue fixed in 8222334.
 178          */
 179         checkMinStackAllowed("0k");
 180     }
 181 }