8177522: -XX:OnOutOfMemoryError does not work if supplied twice on windows
authorvkempik
Thu, 18 May 2017 08:14:33 -0400
changeset 46476 8ead62daaa47
parent 46474 c872a196b75f
child 46477 50faf1da054c
8177522: -XX:OnOutOfMemoryError does not work if supplied twice on windows Summary: use cmd /c on windows to execute onError commands Reviewed-by: dholmes, hseigel
hotspot/src/os/windows/vm/os_windows.cpp
hotspot/src/share/vm/utilities/vmError.cpp
hotspot/test/runtime/ErrorHandling/TestOnOutOfMemoryError.java
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Wed May 17 23:36:19 2017 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Thu May 18 08:14:33 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -5250,12 +5250,30 @@
 int os::fork_and_exec(char* cmd) {
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
-
+  DWORD exit_code;
+
+  char * cmd_string;
+  char * cmd_prefix = "cmd /C ";
+  size_t len = strlen(cmd) + strlen(cmd_prefix) + 1;
+  cmd_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, len, mtInternal);
+  if (cmd_string == NULL) {
+    return -1;
+  }
+  cmd_string[0] = '\0';
+  strcat(cmd_string, cmd_prefix);
+  strcat(cmd_string, cmd);
+
+  // now replace all '\n' with '&'
+  char * substring = cmd_string;
+  while ((substring = strchr(substring, '\n')) != NULL) {
+    substring[0] = '&';
+    substring++;
+  }
   memset(&si, 0, sizeof(si));
   si.cb = sizeof(si);
   memset(&pi, 0, sizeof(pi));
   BOOL rslt = CreateProcess(NULL,   // executable name - use command line
-                            cmd,    // command line
+                            cmd_string,    // command line
                             NULL,   // process security attribute
                             NULL,   // thread security attribute
                             TRUE,   // inherits system handles
@@ -5269,17 +5287,17 @@
     // Wait until child process exits.
     WaitForSingleObject(pi.hProcess, INFINITE);
 
-    DWORD exit_code;
     GetExitCodeProcess(pi.hProcess, &exit_code);
 
     // Close process and thread handles.
     CloseHandle(pi.hProcess);
     CloseHandle(pi.hThread);
-
-    return (int)exit_code;
   } else {
-    return -1;
-  }
+    exit_code = -1;
+  }
+
+  FREE_C_HEAP_ARRAY(char, cmd_string);
+  return (int)exit_code;
 }
 
 bool os::find(address addr, outputStream* st) {
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Wed May 17 23:36:19 2017 +0200
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Thu May 18 08:14:33 2017 -0400
@@ -1396,6 +1396,8 @@
       out.print_raw   ("/bin/sh -c ");
 #elif defined(SOLARIS)
       out.print_raw   ("/usr/bin/sh -c ");
+#elif defined(WINDOWS)
+      out.print_raw   ("cmd /C ");
 #endif
       out.print_raw   ("\"");
       out.print_raw   (cmd);
--- a/hotspot/test/runtime/ErrorHandling/TestOnOutOfMemoryError.java	Wed May 17 23:36:19 2017 +0200
+++ b/hotspot/test/runtime/ErrorHandling/TestOnOutOfMemoryError.java	Thu May 18 08:14:33 2017 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,11 @@
 
 /*
  * @test TestOnOutOfMemoryError
- * @summary Test using -XX:OnOutOfMemoryError=<cmd>
+ * @summary Test using single and multiple -XX:OnOutOfMemoryError=<cmd>
  * @modules java.base/jdk.internal.misc
  * @library /test/lib
  * @run main TestOnOutOfMemoryError
- * @bug 8078470
+ * @bug 8078470 8177522
  */
 
 import jdk.test.lib.process.ProcessTools;
@@ -44,13 +44,22 @@
         }
 
         // else this is the main test
-        String msg = "Test Succeeded";
-        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
-           "-XX:OnOutOfMemoryError=echo " + msg,
+        String msg1 = "Test1 Succeeded";
+        String msg2 = "Test2 Succeeded";
+        ProcessBuilder pb_single = ProcessTools.createJavaProcessBuilder(
+           "-XX:OnOutOfMemoryError=echo " + msg1,
            TestOnOutOfMemoryError.class.getName(),
            "throwOOME");
 
-        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        ProcessBuilder pb_multiple = ProcessTools.createJavaProcessBuilder(
+           "-XX:OnOutOfMemoryError=echo " + msg1,
+           "-XX:OnOutOfMemoryError=echo " + msg2,
+           TestOnOutOfMemoryError.class.getName(),
+           "throwOOME");
+
+        OutputAnalyzer output_single = new OutputAnalyzer(pb_single.start());
+
+        OutputAnalyzer output_multiple = new OutputAnalyzer(pb_multiple.start());
 
         /* Actual output should look like this:
            #
@@ -64,8 +73,13 @@
            So we don't want to match on the "# Executing ..." line, and they
            both get written to stdout.
         */
-        output.shouldContain("Requested array size exceeds VM limit");
-        output.stdoutShouldMatch("^" + msg); // match start of line only
+        output_single.shouldContain("Requested array size exceeds VM limit");
+        output_single.stdoutShouldMatch("^" + msg1); // match start of line only
+
+        output_multiple.shouldContain("Requested array size exceeds VM limit");
+        output_multiple.stdoutShouldMatch("^" + msg1); // match start of line only
+        output_multiple.stdoutShouldMatch("^" + msg2); // match start of line only
+
         System.out.println("PASSED");
     }
 }