From b48d4df404756872fb7b1ef7be5f9880ba6a0abc Mon Sep 17 00:00:00 2001
From: zhangyunbo <zhangyunbo7@huawei.com>
Date: Sun, 29 Jan 2023 10:44:01 +0800
Subject: [PATCH 07/15] 8074354: Make CreateMinidumpOnCrash a new name and
 available on all platforms

DTS/AR: AR.SR.ccd816c9.001
Summary: <JDK> :8074354: Make CreateMinidumpOnCrash a new name and available on all platforms
LLT: NA
Patch Type: backport
Bug url: https://bugs.openjdk.org/browse/JDK-8074354
---
 hotspot/src/os/aix/vm/os_aix.cpp              |   4 +
 hotspot/src/os/bsd/vm/os_bsd.cpp              |   4 +
 hotspot/src/os/linux/vm/os_linux.cpp          |   4 +
 hotspot/src/os/posix/vm/os_posix.cpp          |   4 +-
 hotspot/src/os/solaris/vm/os_solaris.cpp      |   4 +
 hotspot/src/os/windows/vm/os_windows.cpp      | 117 +++++++++---------
 hotspot/src/share/vm/runtime/arguments.cpp    |   9 ++
 hotspot/src/share/vm/runtime/globals.hpp      |   4 +-
 hotspot/src/share/vm/runtime/os.hpp           |  10 +-
 hotspot/src/share/vm/utilities/vmError.cpp    |  19 +--
 hotspot/src/share/vm/utilities/vmError.hpp    |   6 +-
 hotspot/test/runtime/Unsafe/RangeCheck.java   |   1 +
 .../runtime/memory/ReadFromNoaccessArea.java  |   1 +
 .../test/runtime/memory/ReserveMemory.java    |   1 +
 14 files changed, 111 insertions(+), 77 deletions(-)

diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index 519b08550..6838f33bc 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -1214,6 +1214,10 @@ void os::shutdown() {
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
 void os::abort(bool dump_core) {
+  abort(dump_core, NULL, NULL);
+}
+
+void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
 #ifndef PRODUCT
diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp
index 85e28619c..765b60c0d 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp
@@ -1147,6 +1147,10 @@ void os::shutdown() {
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
 void os::abort(bool dump_core) {
+  abort(dump_core, NULL, NULL);
+}
+
+void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
 #ifndef PRODUCT
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index b82352c9f..05c8b254c 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -1588,6 +1588,10 @@ void os::shutdown() {
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
 void os::abort(bool dump_core) {
+  abort(dump_core, NULL, NULL);
+}
+
+void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
 #ifndef PRODUCT
diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp
index d2663bd86..678a1059f 100644
--- a/hotspot/src/os/posix/vm/os_posix.cpp
+++ b/hotspot/src/os/posix/vm/os_posix.cpp
@@ -48,7 +48,7 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 #define ROOT_UID 0
 
 // Check core dump limit and report possible place where core can be found
-void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) {
+void os::check_dump_limit(char* buffer, size_t bufferSize) {
   int n;
   struct rlimit rlim;
   bool success;
@@ -74,7 +74,7 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
         break;
     }
   }
-  VMError::report_coredump_status(buffer, success);
+  VMError::record_coredump_status(buffer, success);
 }
 
 int os::get_native_stack(address* stack, int frames, int toSkip) {
diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp
index d995f51e3..9f8c6a9bf 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp
@@ -1581,6 +1581,10 @@ void os::shutdown() {
 // called from signal handler. Before adding something to os::abort(), make
 // sure it is async-safe and can handle partially initialized VM.
 void os::abort(bool dump_core) {
+  abort(dump_core, NULL, NULL);
+}
+
+void os::abort(bool dump_core, void* siginfo, void* context) {
   os::shutdown();
   if (dump_core) {
 #ifndef PRODUCT
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 23dec5b67..11bd14f6f 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -980,7 +980,43 @@ void os::shutdown() {
 static BOOL  (WINAPI *_MiniDumpWriteDump)  ( HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, PMINIDUMP_EXCEPTION_INFORMATION,
                                             PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION);
 
-void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) {
+static HANDLE dumpFile = NULL;
+
+// Check if dump file can be created.
+void os::check_dump_limit(char* buffer, size_t buffsz) {
+  bool status = true;
+  if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
+    jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
+    status = false;
+  }
+
+#ifndef ASSERT
+  if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
+    jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");
+    status = false;
+  }
+#endif
+
+  if (status) {
+    const char* cwd = get_current_directory(NULL, 0);
+    int pid = current_process_id();
+    if (cwd != NULL) {
+      jio_snprintf(buffer, buffsz, "%s\\hs_err_pid%u.mdmp", cwd, pid);
+    } else {
+      jio_snprintf(buffer, buffsz, ".\\hs_err_pid%u.mdmp", pid);
+    }
+
+    if (dumpFile == NULL &&
+       (dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
+                 == INVALID_HANDLE_VALUE) {
+      jio_snprintf(buffer, buffsz, "Failed to create minidump file (0x%x).", GetLastError());
+      status = false;
+    }
+  }
+  VMError::record_coredump_status(buffer, status);
+}
+
+void os::abort(bool dump_core, void* siginfo, void* context) {
   HINSTANCE dbghelp;
   EXCEPTION_POINTERS ep;
   MINIDUMP_EXCEPTION_INFORMATION mei;
@@ -988,33 +1024,22 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
 
   HANDLE hProcess = GetCurrentProcess();
   DWORD processId = GetCurrentProcessId();
-  HANDLE dumpFile;
   MINIDUMP_TYPE dumpType;
-  static const char* cwd;
 
-// Default is to always create dump for debug builds, on product builds only dump on server versions of Windows.
-#ifndef ASSERT
-  // If running on a client version of Windows and user has not explicitly enabled dumping
-  if (!os::win32::is_windows_server() && !CreateMinidumpOnCrash) {
-    VMError::report_coredump_status("Minidumps are not enabled by default on client versions of Windows", false);
-    return;
-    // If running on a server version of Windows and user has explictly disabled dumping
-  } else if (os::win32::is_windows_server() && !FLAG_IS_DEFAULT(CreateMinidumpOnCrash) && !CreateMinidumpOnCrash) {
-    VMError::report_coredump_status("Minidump has been disabled from the command line", false);
-    return;
-  }
-#else
-  if (!FLAG_IS_DEFAULT(CreateMinidumpOnCrash) && !CreateMinidumpOnCrash) {
-    VMError::report_coredump_status("Minidump has been disabled from the command line", false);
-    return;
+  shutdown();
+  if (!dump_core || dumpFile == NULL) {
+    if (dumpFile != NULL) {
+      CloseHandle(dumpFile);
+    }
+    win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
   }
-#endif
 
   dbghelp = os::win32::load_Windows_dll("DBGHELP.DLL", NULL, 0);
 
   if (dbghelp == NULL) {
-    VMError::report_coredump_status("Failed to load dbghelp.dll", false);
-    return;
+    jio_fprintf(stderr, "Failed to load dbghelp.dll\n");
+    CloseHandle(dumpFile);
+    win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
   }
 
   _MiniDumpWriteDump = CAST_TO_FN_PTR(
@@ -1023,30 +1048,22 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
     GetProcAddress(dbghelp, "MiniDumpWriteDump"));
 
   if (_MiniDumpWriteDump == NULL) {
-    VMError::report_coredump_status("Failed to find MiniDumpWriteDump() in module dbghelp.dll", false);
-    return;
+    jio_fprintf(stderr, "Failed to find MiniDumpWriteDump() in module dbghelp.dll.\n");
+    CloseHandle(dumpFile);
+    win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
   }
 
   dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData);
 
-// Older versions of dbghelp.h doesn't contain all the dumptypes we want, dbghelp.h with
-// API_VERSION_NUMBER 11 or higher contains the ones we want though
+  // Older versions of dbghelp.h do not contain all the dumptypes we want, dbghelp.h with
+  // API_VERSION_NUMBER 11 or higher contains the ones we want though
 #if API_VERSION_NUMBER >= 11
   dumpType = (MINIDUMP_TYPE)(dumpType | MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo |
     MiniDumpWithUnloadedModules);
 #endif
-
-  cwd = get_current_directory(NULL, 0);
-  jio_snprintf(buffer, bufferSize, "%s\\hs_err_pid%u.mdmp",cwd, current_process_id());
-  dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-
-  if (dumpFile == INVALID_HANDLE_VALUE) {
-    VMError::report_coredump_status("Failed to create file for dumping", false);
-    return;
-  }
-  if (exceptionRecord != NULL && contextRecord != NULL) {
-    ep.ContextRecord = (PCONTEXT) contextRecord;
-    ep.ExceptionRecord = (PEXCEPTION_RECORD) exceptionRecord;
+  if (siginfo != NULL && context != NULL) {
+    ep.ContextRecord = (PCONTEXT) context;
+    ep.ExceptionRecord = (PEXCEPTION_RECORD) siginfo;
 
     mei.ThreadId = GetCurrentThreadId();
     mei.ExceptionPointers = &ep;
@@ -1055,40 +1072,20 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char*
     pmei = NULL;
   }
 
-
   // Older versions of dbghelp.dll (the one shipped with Win2003 for example) may not support all
   // the dump types we really want. If first call fails, lets fall back to just use MiniDumpWithFullMemory then.
   if (_MiniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) == false &&
       _MiniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL) == false) {
-        DWORD error = GetLastError();
-        LPTSTR msgbuf = NULL;
-
-        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                      FORMAT_MESSAGE_FROM_SYSTEM |
-                      FORMAT_MESSAGE_IGNORE_INSERTS,
-                      NULL, error, 0, (LPTSTR)&msgbuf, 0, NULL) != 0) {
-
-          jio_snprintf(buffer, bufferSize, "Call to MiniDumpWriteDump() failed (Error 0x%x: %s)", error, msgbuf);
-          LocalFree(msgbuf);
-        } else {
-          // Call to FormatMessage failed, just include the result from GetLastError
-          jio_snprintf(buffer, bufferSize, "Call to MiniDumpWriteDump() failed (Error 0x%x)", error);
-        }
-        VMError::report_coredump_status(buffer, false);
-  } else {
-    VMError::report_coredump_status(buffer, true);
+    jio_fprintf(stderr, "Call to MiniDumpWriteDump() failed (Error 0x%x)\n", GetLastError());
   }
-
   CloseHandle(dumpFile);
+  win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
 }
 
 
-
 void os::abort(bool dump_core)
 {
-  os::shutdown();
-  // no core dump on Windows
-  ::exit(1);
+  abort(dump_core, NULL, NULL);
 }
 
 // Die immediately, no exit hook, no abort hook, no cleanup.
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index b0b541482..43fdd0b49 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -3599,6 +3599,15 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
     } else if (match_jfr_option(&option)) {
       return JNI_EINVAL;
 #endif
+    // CreateMinidumpOnCrash is removed, and replaced by CreateCoredumpOnCrash
+    } else if (match_option(option, "-XX:+CreateMinidumpOnCrash", &tail)) {
+      FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, true);
+      jio_fprintf(defaultStream::output_stream(),
+          "CreateMinidumpOnCrash is replaced by CreateCoredumpOnCrash: CreateCoredumpOnCrash is on\n");
+    } else if (match_option(option, "-XX:-CreateMinidumpOnCrash", &tail)) {
+      FLAG_SET_CMDLINE(bool, CreateCoredumpOnCrash, false);
+      jio_fprintf(defaultStream::output_stream(),
+          "CreateMinidumpOnCrash is replaced by CreateCoredumpOnCrash: CreateCoredumpOnCrash is off\n");
     } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
       // Skip -XX:Flags= since that case has already been handled
       if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) {
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index 3dd4c51a9..3b2776ce5 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -948,8 +948,8 @@ class CommandLineFlags {
   product(bool, ShowMessageBoxOnError, false,                               \
           "Keep process alive on VM fatal error")                           \
                                                                             \
-  product(bool, CreateMinidumpOnCrash, false,                               \
-          "Create minidump on VM fatal error")                              \
+  product(bool, CreateCoredumpOnCrash, true,                                \
+          "Create core/mini dump on VM fatal error")                        \
                                                                             \
   product_pd(bool, UseOSErrorReporting,                                     \
           "Let VM fatal error propagate to the OS (ie. WER on Windows)")    \
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index 092459c99..e696321ab 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -553,6 +553,7 @@ class os: AllStatic {
 
   // Terminate with an error.  Default is to generate a core file on platforms
   // that support such things.  This calls shutdown() and then aborts.
+  static void abort(bool dump_core, void *siginfo, void *context);
   static void abort(bool dump_core = true);
 
   // Die immediately, no exit hook, no abort hook, no cleanup.
@@ -803,8 +804,13 @@ class os: AllStatic {
   // Structured OS Exception support
   static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
 
-  // On Windows this will create an actual minidump, on Linux/Solaris it will simply check core dump limits
-  static void check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize);
+  // On Posix compatible OS it will simply check core dump limits while on Windows
+  // it will check if dump file can be created. Check or prepare a core dump to be
+  // taken at a later point in the same thread in os::abort(). Use the caller
+  // provided buffer as a scratch buffer. The status message which will be written
+  // into the error log either is file location or a short error message, depending
+  // on the checking result.
+  static void check_dump_limit(char* buffer, size_t bufferSize);
 
   // Get the default path to the core file
   // Returns the length of the string
diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp
index 26408fa5e..56ae50fe5 100644
--- a/hotspot/src/share/vm/utilities/vmError.cpp
+++ b/hotspot/src/share/vm/utilities/vmError.cpp
@@ -220,7 +220,7 @@ static void print_bug_submit_message(outputStream *out, Thread *thread) {
 bool VMError::coredump_status;
 char VMError::coredump_message[O_BUFLEN];
 
-void VMError::report_coredump_status(const char* message, bool status) {
+void VMError::record_coredump_status(const char* message, bool status) {
   coredump_status = status;
   strncpy(coredump_message, message, sizeof(coredump_message));
   coredump_message[sizeof(coredump_message)-1] = 0;
@@ -533,10 +533,14 @@ void VMError::report(outputStream* st) {
      }
   STEP(63, "(printing core file information)")
     st->print("# ");
-    if (coredump_status) {
-      st->print("Core dump written. Default location: %s", coredump_message);
+    if (CreateCoredumpOnCrash) {
+      if (coredump_status) {
+        st->print("Core dump will be written. %s", coredump_message);
+      } else {
+        st->print("No core dump will be written. %s", coredump_message);
+      }
     } else {
-      st->print("Failed to write core dump. %s", coredump_message);
+      st->print("CreateCoredumpOnCrash turned off, no core file dumped");
     }
     st->cr();
     st->print_cr("#");
@@ -944,7 +948,7 @@ void VMError::report_and_die() {
   static bool transmit_report_done = false; // done error reporting
 
   if (SuppressFatalErrorMessage) {
-      os::abort();
+      os::abort(CreateCoredumpOnCrash);
   }
   jlong mytid = os::current_thread_id();
   if (first_error == NULL &&
@@ -962,8 +966,7 @@ void VMError::report_and_die() {
       ShowMessageBoxOnError = false;
     }
 
-    // Write a minidump on Windows, check core dump limits on Linux/Solaris
-    os::check_or_create_dump(_siginfo, _context, buffer, sizeof(buffer));
+    os::check_dump_limit(buffer, sizeof(buffer));
 
     // reset signal handlers or exception filter; make sure recursive crashes
     // are handled properly.
@@ -1153,7 +1156,7 @@ void VMError::report_and_die() {
     if (!skip_os_abort) {
       skip_os_abort = true;
       bool dump_core = should_report_bug(first_error->_id);
-      os::abort(dump_core);
+      os::abort(dump_core && CreateCoredumpOnCrash, _siginfo, _context);
     }
 
     // if os::abort() doesn't abort, try os::die();
diff --git a/hotspot/src/share/vm/utilities/vmError.hpp b/hotspot/src/share/vm/utilities/vmError.hpp
index 21db84d0c..dc455c6fa 100644
--- a/hotspot/src/share/vm/utilities/vmError.hpp
+++ b/hotspot/src/share/vm/utilities/vmError.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, 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
@@ -117,8 +117,8 @@ public:
   // return a string to describe the error
   char *error_string(char* buf, int buflen);
 
-  // Report status of core/minidump
-  static void report_coredump_status(const char* message, bool status);
+  // Record status of core/minidump
+  static void record_coredump_status(const char* message, bool status);
 
   // main error reporting function
   void report_and_die();
diff --git a/hotspot/test/runtime/Unsafe/RangeCheck.java b/hotspot/test/runtime/Unsafe/RangeCheck.java
index 9ded944cb..602f22500 100644
--- a/hotspot/test/runtime/Unsafe/RangeCheck.java
+++ b/hotspot/test/runtime/Unsafe/RangeCheck.java
@@ -43,6 +43,7 @@ public class RangeCheck {
                 true,
                 "-Xmx32m",
                 "-XX:-TransmitErrorReport",
+                "-XX:-CreateCoredumpOnCrash",
                 DummyClassWithMainRangeCheck.class.getName());
 
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
diff --git a/hotspot/test/runtime/memory/ReadFromNoaccessArea.java b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java
index 1078dd2e4..b2a58ae0a 100644
--- a/hotspot/test/runtime/memory/ReadFromNoaccessArea.java
+++ b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java
@@ -45,6 +45,7 @@ public class ReadFromNoaccessArea {
           "-Xbootclasspath/a:.",
           "-XX:+UnlockDiagnosticVMOptions",
           "-XX:+WhiteBoxAPI",
+          "-XX:-CreateCoredumpOnCrash",
           "-XX:+UseCompressedOops",
           "-XX:HeapBaseMinAddress=33G",
           DummyClassWithMainTryingToReadFromNoaccessArea.class.getName());
diff --git a/hotspot/test/runtime/memory/ReserveMemory.java b/hotspot/test/runtime/memory/ReserveMemory.java
index 9e37d52cc..ef4dde1a7 100644
--- a/hotspot/test/runtime/memory/ReserveMemory.java
+++ b/hotspot/test/runtime/memory/ReserveMemory.java
@@ -57,6 +57,7 @@ public class ReserveMemory {
           "-XX:+UnlockDiagnosticVMOptions",
           "-XX:+WhiteBoxAPI",
           "-XX:-TransmitErrorReport",
+          "-XX:-CreateCoredumpOnCrash",
           "ReserveMemory",
           "test");
 
-- 
2.19.0

