Date: Fri, 9 Jun 2023 09:45:23 +0800
Subject: [PATCH 38/59] Record file descriptor when ExtensiveErrorReports is enabled

---
 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       | 40 ++++++++++++++++++++++
 hotspot/src/os/solaris/vm/os_solaris.cpp   |  4 +++
 hotspot/src/os/windows/vm/os_windows.cpp   |  4 +++
 hotspot/src/share/vm/runtime/os.cpp        |  7 ++++
 hotspot/src/share/vm/runtime/os.hpp        |  2 ++
 hotspot/src/share/vm/utilities/vmError.cpp | 10 ++++++
 8 files changed, 75 insertions(+)

diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index 6838f33bc..2cf08dce1 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -1617,6 +1617,10 @@ void os::pd_print_cpu_info(outputStream* st) {
   st->cr();
 }
 
+void os::pd_print_file_descriptor(outputStream* st) {
+  // Nothing to do for now.
+}
+
 void os::print_siginfo(outputStream* st, void* siginfo) {
   // Use common posix version.
   os::Posix::print_siginfo_brief(st, (const siginfo_t*) siginfo);
diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp
index 765b60c0d..7942c8545 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp
@@ -1779,6 +1779,10 @@ void os::print_memory_info(outputStream* st) {
   st->cr();
 }
 
+void os::pd_print_file_descriptor(outputStream* st) {
+  // Nothing to do for now.
+}
+
 void os::print_siginfo(outputStream* st, void* siginfo) {
   const siginfo_t* si = (const siginfo_t*)siginfo;
 
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index e875fee77..b82997568 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -2509,6 +2509,46 @@ void os::print_siginfo(outputStream* st, void* siginfo) {
   st->cr();
 }
 
+// max length of file name in linux
+#define MAX_PATH_LEN 256
+// maximum number of file descriptors to print
+#define MAX_PRINT_FD_SIZE 2000
+
+void os::pd_print_file_descriptor(outputStream* st) {
+  int pid = os::current_process_id();
+  char process_path[MAX_PATH_LEN] = {0};
+  (void) snprintf(process_path, MAX_PATH_LEN, "/proc/%d/fd/", pid);
+  st->print_cr("path: %s", process_path);
+
+  DIR *dir = NULL;
+  dir = opendir(process_path);
+  if (dir == NULL) {
+    st->print_cr("opendir %s failed, errno: %d", process_path, errno);
+    return;
+  }
+
+  // Scan the directory, get symbolic link value
+  struct dirent *ptr;
+  ssize_t readlink_ret = 0;
+  char symbolic_link_value[MAX_PATH_LEN] = {0};
+  char filename[MAX_PATH_LEN] = {0};
+  unsigned long file_count = 0;
+  while ((ptr = readdir(dir)) != NULL) {
+    if (ptr->d_type == DT_DIR) continue;
+    if (file_count < MAX_PRINT_FD_SIZE) {
+      (void) snprintf(filename, MAX_PATH_LEN, "%s%s", process_path, ptr->d_name);
+      readlink_ret = readlink(filename, symbolic_link_value, MAX_PATH_LEN);
+      if (readlink_ret > 0) {
+        st->print_cr("%s -> %s", ptr->d_name, symbolic_link_value);
+      } else {
+        st->print_cr("%s: readlink failed, errno: %d", ptr->d_name, errno);
+      }
+    }
+    file_count++;
+  }
+  st->print_cr("Total fd count: %lu", file_count);
+  (void) closedir(dir);
+}
 
 static void print_signal_handler(outputStream* st, int sig,
                                  char* buf, size_t buflen);
diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp
index 9f8c6a9bf..9029238e1 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp
@@ -2094,6 +2094,10 @@ void os::pd_print_cpu_info(outputStream* st) {
   // Nothing to do for now.
 }
 
+void os::pd_print_file_descriptor(outputStream* st) {
+  // Nothing to do for now.
+}
+
 void os::print_memory_info(outputStream* st) {
   st->print("Memory:");
   st->print(" %dk page", os::vm_page_size()>>10);
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index f0bc733c2..1017147c8 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -1865,6 +1865,10 @@ void os::pd_print_cpu_info(outputStream* st) {
   // Nothing to do for now.
 }
 
+void os::pd_print_file_descriptor(outputStream* st) {
+  // Nothing to do for now.
+}
+
 void os::print_memory_info(outputStream* st) {
   st->print("Memory:");
   st->print(" %dk page", os::vm_page_size()>>10);
diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp
index 84841b76e..43d66e85e 100644
--- a/hotspot/src/share/vm/runtime/os.cpp
+++ b/hotspot/src/share/vm/runtime/os.cpp
@@ -861,6 +861,13 @@ void os::print_hex_dump(outputStream* st, address start, address end, int unitsi
   st->cr();
 }
 
+void os::print_file_descriptor(outputStream* st) {
+  // file descriptor
+  st->print("File Descriptor:");
+  st->cr();
+  pd_print_file_descriptor(st);
+}
+
 void os::print_environment_variables(outputStream* st, const char** env_list,
                                      char* buffer, int len) {
   if (env_list) {
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index 6ca220021..988977b17 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -661,6 +661,8 @@ class os: AllStatic {
   static void print_siginfo(outputStream* st, void* siginfo);
   static void print_signal_handlers(outputStream* st, char* buf, size_t buflen);
   static void print_date_and_time(outputStream* st, char* buf, size_t buflen);
+  static void print_file_descriptor(outputStream* st);
+  static void pd_print_file_descriptor(outputStream* st);
 
   static void print_location(outputStream* st, intptr_t x, bool verbose = false);
   static size_t lasterror(char *buf, size_t len);
diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp
index 5bbfade6c..0c5c955bf 100644
--- a/hotspot/src/share/vm/utilities/vmError.cpp
+++ b/hotspot/src/share/vm/utilities/vmError.cpp
@@ -810,6 +810,16 @@ void VMError::report(outputStream* st) {
        st->cr();
      }
 
+#if defined(AARCH64) || defined(X86)
+  STEP(207, "(printing file descriptor)" )
+
+     if (ExtensiveErrorReports && _verbose) {
+       // File Descriptor
+       os::print_file_descriptor(st);
+       st->cr();
+     }
+#endif
+
   STEP(210, "(printing VM options)" )
 
      if (_verbose) {
-- 
2.22.0

