changeset 59279:44c24e779d51

8235211: serviceability/attach/RemovingUnixDomainSocketTest.java fails with AttachNotSupportedException: Unable to open socket file Reviewed-by: sspitsyn, ysuenaga
author amenkov
date Wed, 13 May 2020 15:25:59 -0700
parents 26a4100f7102
children a5f3e4dbd852
files src/hotspot/os/aix/attachListener_aix.cpp src/hotspot/os/bsd/attachListener_bsd.cpp src/hotspot/os/linux/attachListener_linux.cpp test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java test/lib/jdk/test/lib/apps/LingeredApp.java
diffstat 5 files changed, 66 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/os/aix/attachListener_aix.cpp	Wed May 13 17:01:10 2020 -0400
+++ b/src/hotspot/os/aix/attachListener_aix.cpp	Wed May 13 15:25:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -66,10 +66,10 @@
   static char _path[UNIX_PATH_MAX];
   static bool _has_path;
   // Shutdown marker to prevent accept blocking during clean-up.
-  static bool _shutdown;
+  static volatile bool _shutdown;
 
   // the file descriptor for the listening socket
-  static int _listener;
+  static volatile int _listener;
 
   static bool _atexit_registered;
 
@@ -132,10 +132,10 @@
 // statics
 char AixAttachListener::_path[UNIX_PATH_MAX];
 bool AixAttachListener::_has_path;
-int AixAttachListener::_listener = -1;
+volatile int AixAttachListener::_listener = -1;
 bool AixAttachListener::_atexit_registered = false;
 // Shutdown marker to prevent accept blocking during clean-up
-bool AixAttachListener::_shutdown = false;
+volatile bool AixAttachListener::_shutdown = false;
 
 // Supporting class to help split a buffer into individual components
 class ArgumentIterator : public StackObj {
@@ -184,7 +184,6 @@
     AixAttachListener::set_shutdown(true);
     int s = AixAttachListener::listener();
     if (s != -1) {
-      AixAttachListener::set_listener(-1);
       ::shutdown(s, 2);
     }
     if (AixAttachListener::has_path()) {
@@ -376,10 +375,14 @@
     // We must prevent accept blocking on the socket if it has been shut down.
     // Therefore we allow interrupts and check whether we have been shut down already.
     if (AixAttachListener::is_shutdown()) {
+      ::close(listener());
+      set_listener(-1);
       return NULL;
     }
-    s=::accept(listener(), &addr, &len);
+    s = ::accept(listener(), &addr, &len);
     if (s == -1) {
+      ::close(listener());
+      set_listener(-1);
       return NULL;      // log a warning?
     }
 
@@ -531,9 +534,13 @@
     listener_cleanup();
 
     // wait to terminate current attach listener instance...
-    while (AttachListener::transit_state(AL_INITIALIZING,
-                                         AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
-      os::naked_yield();
+    {
+      // avoid deadlock if AttachListener thread is blocked at safepoint
+      ThreadBlockInVM tbivm(JavaThread::current());
+      while (AttachListener::transit_state(AL_INITIALIZING,
+                                           AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
+        os::naked_yield();
+      }
     }
     return is_init_trigger();
   }
--- a/src/hotspot/os/bsd/attachListener_bsd.cpp	Wed May 13 17:01:10 2020 -0400
+++ b/src/hotspot/os/bsd/attachListener_bsd.cpp	Wed May 13 15:25:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -66,7 +66,7 @@
   static bool _has_path;
 
   // the file descriptor for the listening socket
-  static int _listener;
+  static volatile int _listener;
 
   static bool _atexit_registered;
 
@@ -126,7 +126,7 @@
 // statics
 char BsdAttachListener::_path[UNIX_PATH_MAX];
 bool BsdAttachListener::_has_path;
-int BsdAttachListener::_listener = -1;
+volatile int BsdAttachListener::_listener = -1;
 bool BsdAttachListener::_atexit_registered = false;
 
 // Supporting class to help split a buffer into individual components
@@ -502,11 +502,13 @@
     listener_cleanup();
 
     // wait to terminate current attach listener instance...
-
-    while (AttachListener::transit_state(AL_INITIALIZING,
-
-                                         AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
-      os::naked_yield();
+    {
+      // avoid deadlock if AttachListener thread is blocked at safepoint
+      ThreadBlockInVM tbivm(JavaThread::current());
+      while (AttachListener::transit_state(AL_INITIALIZING,
+                                           AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
+        os::naked_yield();
+      }
     }
     return is_init_trigger();
   }
--- a/src/hotspot/os/linux/attachListener_linux.cpp	Wed May 13 17:01:10 2020 -0400
+++ b/src/hotspot/os/linux/attachListener_linux.cpp	Wed May 13 15:25:59 2020 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, 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
@@ -67,7 +67,7 @@
   static bool _has_path;
 
   // the file descriptor for the listening socket
-  static int _listener;
+  static volatile int _listener;
 
   static bool _atexit_registered;
 
@@ -127,7 +127,7 @@
 // statics
 char LinuxAttachListener::_path[UNIX_PATH_MAX];
 bool LinuxAttachListener::_has_path;
-int LinuxAttachListener::_listener = -1;
+volatile int LinuxAttachListener::_listener = -1;
 bool LinuxAttachListener::_atexit_registered = false;
 
 // Supporting class to help split a buffer into individual components
@@ -502,9 +502,13 @@
     listener_cleanup();
 
     // wait to terminate current attach listener instance...
-    while (AttachListener::transit_state(AL_INITIALIZING,
-                                         AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
-      os::naked_yield();
+    {
+      // avoid deadlock if AttachListener thread is blocked at safepoint
+      ThreadBlockInVM tbivm(JavaThread::current());
+      while (AttachListener::transit_state(AL_INITIALIZING,
+                                           AL_NOT_INITIALIZED) != AL_NOT_INITIALIZED) {
+        os::naked_yield();
+      }
     }
     return is_init_trigger();
   }
--- a/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java	Wed May 13 17:01:10 2020 -0400
+++ b/test/hotspot/jtreg/serviceability/attach/RemovingUnixDomainSocketTest.java	Wed May 13 15:25:59 2020 -0700
@@ -29,33 +29,44 @@
  * @run main RemovingUnixDomainSocketTest
  */
 
+import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
 
 import jdk.test.lib.Utils;
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.JDKToolLauncher;
 import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
 
 public class RemovingUnixDomainSocketTest {
 
+    // timeout (in seconds)
+    private static final long timeout = Utils.adjustTimeout(60);
+
     private static void runJCmd(long pid) throws InterruptedException, IOException {
         JDKToolLauncher jcmd = JDKToolLauncher.createUsingTestJDK("jcmd");
         jcmd.addVMArgs(Utils.getTestJavaOpts());
         jcmd.addToolArg(Long.toString(pid));
         jcmd.addToolArg("VM.version");
 
-        ProcessBuilder pb = new ProcessBuilder(jcmd.getCommand());
-        Process jcmdProc = pb.start();
+        Process jcmdProc = ProcessTools.startProcess("jcmd", new ProcessBuilder(jcmd.getCommand()));
 
         OutputAnalyzer out = new OutputAnalyzer(jcmdProc);
 
-        jcmdProc.waitFor();
+        if (!jcmdProc.waitFor(timeout, TimeUnit.SECONDS)) {
+            log("jcmd is still running after " + timeout + " seconds, terminating...");
+            jcmdProc.destroy();
+            jcmdProc.waitFor();
+        }
 
-        System.out.println(out.getStdout());
-        System.err.println(out.getStderr());
+        log("jcmd stdout: [" + out.getStdout() + "];\n" +
+            "jcmd  stderr: [" + out.getStderr() + "]\n" +
+            "jcmd  exitValue = " + out.getExitValue());
 
-        out.stderrShouldBeEmptyIgnoreVMWarnings();
+        out.stderrShouldBeEmptyIgnoreVMWarnings()
+                .stderrShouldBeEmpty();
     }
 
     public static void main(String... args) throws Exception {
@@ -67,10 +78,10 @@
             runJCmd(app.getPid());
 
             // Remove unix domain socket file
-            var sockFile = Path.of(System.getProperty("java.io.tmpdir"),
+            File sockFile = Path.of(System.getProperty("java.io.tmpdir"),
                                    ".java_pid" + app.getPid())
                                .toFile();
-            System.out.println("Remove " + sockFile.toString());
+            log("Remove " + sockFile.toString());
             sockFile.delete();
 
             // Access to Attach Listener again
@@ -80,4 +91,7 @@
         }
     }
 
+    static void log(Object s) {
+        System.out.println(String.valueOf(s));
+    }
 }
--- a/test/lib/jdk/test/lib/apps/LingeredApp.java	Wed May 13 17:01:10 2020 -0400
+++ b/test/lib/jdk/test/lib/apps/LingeredApp.java	Wed May 13 15:25:59 2020 -0700
@@ -36,6 +36,7 @@
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.UUID;
 
@@ -224,7 +225,11 @@
     public void waitAppTerminate() {
         // This code is modeled after tail end of ProcessTools.getOutput().
         try {
-            appProcess.waitFor();
+            // If the app hangs, we don't want to wait for the to test timeout.
+            if (!appProcess.waitFor(Utils.adjustTimeout(appWaitTime), TimeUnit.SECONDS)) {
+                appProcess.destroy();
+                appProcess.waitFor();
+            }
             outPumperThread.join();
             errPumperThread.join();
         } catch (InterruptedException e) {
@@ -270,7 +275,7 @@
     }
 
     /**
-     * Waits the application to start with the default timeout.
+     * Waits for the application to start with the default timeout.
      */
     public void waitAppReady() throws IOException {
         waitAppReady(appWaitTime);