302 lines
10 KiB
Diff
302 lines
10 KiB
Diff
From 120367d947c297709134167d3e4d8e1b91fe97f3 Mon Sep 17 00:00:00 2001
|
|
From: z30010524 <zhangyunbo7@huawei.com>
|
|
Date: Tue, 14 Mar 2023 19:17:50 +0800
|
|
Subject: [PATCH 10/15] 8057743: (process) Synchronize exiting of threads and
|
|
process [win]
|
|
|
|
DTS/AR: DTS2023031516597
|
|
Summary: <JDK> :8057744: (process) Synchronize exiting of threads and process [win]
|
|
LLT: NA
|
|
Patch Type: backport
|
|
Bug url: https://bugs.openjdk.org/browse/JDK-8057744
|
|
---
|
|
hotspot/src/os/aix/vm/os_aix.inline.hpp | 5 ++
|
|
hotspot/src/os/bsd/vm/os_bsd.inline.hpp | 4 +
|
|
hotspot/src/os/linux/vm/os_linux.inline.hpp | 4 +
|
|
.../src/os/solaris/vm/os_solaris.inline.hpp | 5 ++
|
|
hotspot/src/os/windows/vm/os_windows.cpp | 87 +++++++++++++++++--
|
|
hotspot/src/os/windows/vm/os_windows.hpp | 10 +++
|
|
.../src/os/windows/vm/os_windows.inline.hpp | 4 +
|
|
hotspot/src/share/vm/runtime/java.cpp | 2 +-
|
|
hotspot/src/share/vm/runtime/os.hpp | 4 +-
|
|
9 files changed, 115 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/hotspot/src/os/aix/vm/os_aix.inline.hpp b/hotspot/src/os/aix/vm/os_aix.inline.hpp
|
|
index 421ea342e..afa034411 100644
|
|
--- a/hotspot/src/os/aix/vm/os_aix.inline.hpp
|
|
+++ b/hotspot/src/os/aix/vm/os_aix.inline.hpp
|
|
@@ -245,4 +245,9 @@ inline int os::set_sock_opt(int fd, int level, int optname,
|
|
const char* optval, socklen_t optlen) {
|
|
return ::setsockopt(fd, level, optname, optval, optlen);
|
|
}
|
|
+
|
|
+inline void os::exit(int num) {
|
|
+ ::exit(num);
|
|
+}
|
|
+
|
|
#endif // OS_AIX_VM_OS_AIX_INLINE_HPP
|
|
diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
|
|
index c35abf486..1eff6b724 100644
|
|
--- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
|
|
+++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
|
|
@@ -247,4 +247,8 @@ inline int os::set_sock_opt(int fd, int level, int optname,
|
|
return ::setsockopt(fd, level, optname, optval, optlen);
|
|
}
|
|
|
|
+inline void os::exit(int num) {
|
|
+ ::exit(num);
|
|
+}
|
|
+
|
|
#endif // OS_BSD_VM_OS_BSD_INLINE_HPP
|
|
diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp
|
|
index a23bd5631..eb8c8ca1b 100644
|
|
--- a/hotspot/src/os/linux/vm/os_linux.inline.hpp
|
|
+++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp
|
|
@@ -240,4 +240,8 @@ inline int os::set_sock_opt(int fd, int level, int optname,
|
|
return ::setsockopt(fd, level, optname, optval, optlen);
|
|
}
|
|
|
|
+inline void os::exit(int num) {
|
|
+ ::exit(num);
|
|
+}
|
|
+
|
|
#endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP
|
|
diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
|
|
index 8e095ab69..aad6debf9 100644
|
|
--- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
|
|
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
|
|
@@ -223,4 +223,9 @@ inline int os::set_sock_opt(int fd, int level, int optname,
|
|
const char *optval, socklen_t optlen) {
|
|
return ::setsockopt(fd, level, optname, optval, optlen);
|
|
}
|
|
+
|
|
+inline void os::exit(int num) {
|
|
+ ::exit(num);
|
|
+}
|
|
+
|
|
#endif // OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP
|
|
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
|
|
index 11bd14f6f..f0bc733c2 100644
|
|
--- a/hotspot/src/os/windows/vm/os_windows.cpp
|
|
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
|
|
@@ -22,8 +22,8 @@
|
|
*
|
|
*/
|
|
|
|
-// Must be at least Windows 2000 or XP to use IsDebuggerPresent
|
|
-#define _WIN32_WINNT 0x500
|
|
+// Must be at least Windows Vista or Server 2008 to use InitOnceExecuteOnce
|
|
+#define _WIN32_WINNT 0x0600
|
|
|
|
// no precompiled headers
|
|
#include "classfile/classLoader.hpp"
|
|
@@ -432,6 +432,11 @@ static unsigned __stdcall java_start(Thread* thread) {
|
|
}
|
|
}
|
|
|
|
+ // Diagnostic code to investigate JDK-6573254
|
|
+ int res = 90115; // non-java thread
|
|
+ if (thread->is_Java_thread()) {
|
|
+ res = 60115; // java thread
|
|
+ }
|
|
|
|
// Install a win32 structured exception handler around every thread created
|
|
// by VM, so VM can genrate error dump when an exception occurred in non-
|
|
@@ -450,7 +455,9 @@ static unsigned __stdcall java_start(Thread* thread) {
|
|
Atomic::dec_ptr((intptr_t*)&os::win32::_os_thread_count);
|
|
}
|
|
|
|
- return 0;
|
|
+ // Thread must not return from exit_process_or_thread(), but if it does,
|
|
+ // let it proceed to exit normally
|
|
+ return (unsigned)os::win32::exit_process_or_thread(os::win32::EPT_THREAD, res);
|
|
}
|
|
|
|
static OSThread* create_os_thread(Thread* thread, HANDLE thread_handle, int thread_id) {
|
|
@@ -1082,15 +1089,13 @@ void os::abort(bool dump_core, void* siginfo, void* context) {
|
|
win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
|
|
}
|
|
|
|
-
|
|
-void os::abort(bool dump_core)
|
|
-{
|
|
+void os::abort(bool dump_core) {
|
|
abort(dump_core, NULL, NULL);
|
|
}
|
|
|
|
// Die immediately, no exit hook, no abort hook, no cleanup.
|
|
void os::die() {
|
|
- _exit(-1);
|
|
+ win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);
|
|
}
|
|
|
|
// Directory routines copied from src/win32/native/java/io/dirent_md.c
|
|
@@ -3857,6 +3862,11 @@ bool os::win32::_is_nt = false;
|
|
bool os::win32::_is_windows_2003 = false;
|
|
bool os::win32::_is_windows_server = false;
|
|
|
|
+// 6573254
|
|
+// Currently, the bug is observed across all the supported Windows releases,
|
|
+// including the latest one (as of this writing - Windows Server 2012 R2)
|
|
+bool os::win32::_has_exit_bug = true;
|
|
+
|
|
void os::win32::initialize_system_info() {
|
|
SYSTEM_INFO si;
|
|
GetSystemInfo(&si);
|
|
@@ -3951,6 +3961,69 @@ HINSTANCE os::win32::load_Windows_dll(const char* name, char *ebuf, int ebuflen)
|
|
return NULL;
|
|
}
|
|
|
|
+#define MIN_EXIT_MUTEXES 1
|
|
+#define MAX_EXIT_MUTEXES 16
|
|
+
|
|
+struct ExitMutexes {
|
|
+ DWORD count;
|
|
+ HANDLE handles[MAX_EXIT_MUTEXES];
|
|
+};
|
|
+
|
|
+static BOOL CALLBACK init_muts_call(PINIT_ONCE, PVOID ppmuts, PVOID*) {
|
|
+ static ExitMutexes muts;
|
|
+
|
|
+ muts.count = os::processor_count();
|
|
+ if (muts.count < MIN_EXIT_MUTEXES) {
|
|
+ muts.count = MIN_EXIT_MUTEXES;
|
|
+ } else if (muts.count > MAX_EXIT_MUTEXES) {
|
|
+ muts.count = MAX_EXIT_MUTEXES;
|
|
+ }
|
|
+
|
|
+ for (DWORD i = 0; i < muts.count; ++i) {
|
|
+ muts.handles[i] = CreateMutex(NULL, FALSE, NULL);
|
|
+ if (muts.handles[i] == NULL) {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+ *((ExitMutexes**)ppmuts) = &muts;
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+int os::win32::exit_process_or_thread(Ept what, int exit_code) {
|
|
+ if (os::win32::has_exit_bug()) {
|
|
+ static INIT_ONCE init_once_muts = INIT_ONCE_STATIC_INIT;
|
|
+ static ExitMutexes* pmuts;
|
|
+
|
|
+ if (!InitOnceExecuteOnce(&init_once_muts, init_muts_call, &pmuts, NULL)) {
|
|
+ warning("ExitMutex initialization failed in %s: %d\n", __FILE__, __LINE__);
|
|
+ } else if (WaitForMultipleObjects(pmuts->count, pmuts->handles,
|
|
+ (what != EPT_THREAD), // exiting process waits for all mutexes
|
|
+ INFINITE) == WAIT_FAILED) {
|
|
+ warning("ExitMutex acquisition failed in %s: %d\n", __FILE__, __LINE__);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ switch (what) {
|
|
+ case EPT_THREAD:
|
|
+ _endthreadex((unsigned)exit_code);
|
|
+ break;
|
|
+
|
|
+ case EPT_PROCESS:
|
|
+ ::exit(exit_code);
|
|
+ break;
|
|
+
|
|
+ case EPT_PROCESS_DIE:
|
|
+ _exit(exit_code);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ // should not reach here
|
|
+ return exit_code;
|
|
+}
|
|
+
|
|
+#undef MIN_EXIT_MUTEXES
|
|
+#undef MAX_EXIT_MUTEXES
|
|
+
|
|
void os::win32::setmode_streams() {
|
|
_setmode(_fileno(stdin), _O_BINARY);
|
|
_setmode(_fileno(stdout), _O_BINARY);
|
|
diff --git a/hotspot/src/os/windows/vm/os_windows.hpp b/hotspot/src/os/windows/vm/os_windows.hpp
|
|
index 20e2ca2f5..3fdc9bcd6 100644
|
|
--- a/hotspot/src/os/windows/vm/os_windows.hpp
|
|
+++ b/hotspot/src/os/windows/vm/os_windows.hpp
|
|
@@ -31,6 +31,7 @@ static bool zero_page_read_protected() { return true; }
|
|
|
|
class win32 {
|
|
friend class os;
|
|
+ friend unsigned __stdcall java_start(class Thread*);
|
|
|
|
protected:
|
|
static int _vm_page_size;
|
|
@@ -42,6 +43,7 @@ class win32 {
|
|
static bool _is_nt;
|
|
static bool _is_windows_2003;
|
|
static bool _is_windows_server;
|
|
+ static bool _has_exit_bug;
|
|
|
|
static void print_windows_version(outputStream* st);
|
|
|
|
@@ -63,6 +65,11 @@ class win32 {
|
|
// load dll from Windows system directory or Windows directory
|
|
static HINSTANCE load_Windows_dll(const char* name, char *ebuf, int ebuflen);
|
|
|
|
+ private:
|
|
+ enum Ept { EPT_THREAD, EPT_PROCESS, EPT_PROCESS_DIE };
|
|
+ // Wrapper around _endthreadex(), exit() and _exit()
|
|
+ static int exit_process_or_thread(Ept what, int exit_code);
|
|
+
|
|
public:
|
|
// Generic interface:
|
|
|
|
@@ -79,6 +86,9 @@ class win32 {
|
|
// Tells whether the platform is Windows 2003
|
|
static bool is_windows_2003() { return _is_windows_2003; }
|
|
|
|
+ // Tells whether there can be the race bug during process exit on this platform
|
|
+ static bool has_exit_bug() { return _has_exit_bug; }
|
|
+
|
|
// Returns the byte size of a virtual memory page
|
|
static int vm_page_size() { return _vm_page_size; }
|
|
|
|
diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp
|
|
index 5dac11c90..83c51935d 100644
|
|
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp
|
|
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp
|
|
@@ -96,4 +96,8 @@ inline int os::close(int fd) {
|
|
return ::close(fd);
|
|
}
|
|
|
|
+inline void os::exit(int num) {
|
|
+ win32::exit_process_or_thread(win32::EPT_PROCESS, num);
|
|
+}
|
|
+
|
|
#endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
|
|
diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp
|
|
index 5b82a7a36..c72a5a766 100644
|
|
--- a/hotspot/src/share/vm/runtime/java.cpp
|
|
+++ b/hotspot/src/share/vm/runtime/java.cpp
|
|
@@ -625,7 +625,7 @@ void notify_vm_shutdown() {
|
|
void vm_direct_exit(int code) {
|
|
notify_vm_shutdown();
|
|
os::wait_for_keypress_at_exit();
|
|
- ::exit(code);
|
|
+ os::exit(code);
|
|
}
|
|
|
|
void vm_perform_shutdown_actions() {
|
|
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
|
|
index e696321ab..6ca220021 100644
|
|
--- a/hotspot/src/share/vm/runtime/os.hpp
|
|
+++ b/hotspot/src/share/vm/runtime/os.hpp
|
|
@@ -545,8 +545,8 @@ class os: AllStatic {
|
|
// run cmd in a separate process and return its exit code; or -1 on failures
|
|
static int fork_and_exec(char *cmd, bool use_vfork_if_available = false);
|
|
|
|
- // os::exit() is merged with vm_exit()
|
|
- // static void exit(int num);
|
|
+ // Call ::exit() on all platforms but Windows
|
|
+ static void exit(int num);
|
|
|
|
// Terminate the VM, but don't exit the process
|
|
static void shutdown();
|
|
--
|
|
2.19.0
|
|
|