8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out
authoriklam
Tue, 26 Mar 2019 11:34:40 -0700
changeset 54297 f98f158c1db8
parent 54296 dc66ada06693
child 54298 6207397a6603
8217347: [TESTBUG] runtime/appcds/jvmti/InstrumentationTest.java timed out Summary: Avoid using VirtualMachine.list(). Use Process.pid() instead. Reviewed-by: dholmes
test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java
test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java	Tue Mar 26 15:36:19 2019 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationApp.java	Tue Mar 26 11:34:40 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -28,6 +28,7 @@
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.io.File;
+import java.io.FileWriter;
 import java.security.CodeSigner;
 import java.security.CodeSource;
 import java.security.ProtectionDomain;
@@ -140,8 +141,22 @@
     }
 
     static void waitAttach(String flagFile) throws Throwable {
+        // See InstrumentationTest.java for the hand-shake protocol.
         if (!flagFile.equals("noattach")) {
             File f = new File(flagFile);
+            try (FileWriter fw = new FileWriter(f)) {
+                long pid = ProcessHandle.current().pid();
+                System.out.println("my pid = " + pid);
+                fw.write(Long.toString(pid));
+                fw.write("\n");
+                for (int i=0; i<10; i++) {
+                  // Parent process waits until we have written more than 100 bytes, so it won't
+                  // read a partial pid
+                  fw.write("==========");
+                }
+                fw.close();
+            }
+
             long start = System.currentTimeMillis();
             while (f.exists()) {
                 long elapsed = System.currentTimeMillis() - start;
--- a/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java	Tue Mar 26 15:36:19 2019 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/jvmti/InstrumentationTest.java	Tue Mar 26 11:34:40 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -29,9 +29,6 @@
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds /test/hotspot/jtreg/runtime/appcds/test-classes
  * @requires vm.cds
  * @requires vm.flavor != "minimal"
- * @modules java.base/jdk.internal.misc
- *          jdk.jartool/sun.tools.jar
- *          java.management
  * @build sun.hotspot.WhiteBox
  *        InstrumentationApp
  *        InstrumentationClassFileTransformer
@@ -43,10 +40,9 @@
 // Note: Util       is from /test/hotspot/jtreg/runtime/appcds/test-classes/TestCommon.java
 
 import com.sun.tools.attach.VirtualMachine;
-import com.sun.tools.attach.VirtualMachineDescriptor;
 import java.io.File;
-import java.io.FileOutputStream;
-import java.util.List;
+import java.io.FileInputStream;
+import java.util.Scanner;
 import jdk.test.lib.Asserts;
 import jdk.test.lib.cds.CDSOptions;
 import jdk.test.lib.process.OutputAnalyzer;
@@ -179,24 +175,28 @@
             return null;
         }
 
-        // We use the flagFile to prevent the child process to make progress, until we have
-        // attached to it.
+        // Hand-shake protocol with the child process
+        // [1] Parent process (this process) launches child process (InstrumentationApp)
+        //     and then waits until child process writes its pid into the flagFile.
+        // [2] Child process process starts up, writes its pid into the flagFile,
+        //     and waits for the flagFile to be deleted.
+        // [3] When parent process gets the pid, it attaches to the child process
+        //     (if we attempt to attach to a process too early, the SIGQUIT
+        //     may cause the child to die) and deletes the flagFile.
+        // [4] Child process resumes execution.
+
         File f = new File(flagFile);
-        try (FileOutputStream o = new FileOutputStream(f)) {
-            o.write(1);
-        }
-        if (!f.exists()) {
-            throw new RuntimeException("Failed to create " + f);
+        f.delete();
+        if (f.exists()) {
+            throw new RuntimeException("Flag file should not exist: " + f);
         }
 
         // At this point, the child process is not yet launched. Note that
         // TestCommon.exec() and OutputAnalyzer.OutputAnalyzer() both block
         // until the child process has finished.
         //
-        // So, we will launch a AgentAttachThread which will poll the system
-        // until the child process is launched, and then do the attachment.
-        // The child process is uniquely identified by having flagFile in its
-        // command-line -- see AgentAttachThread.getPid().
+        // So, we will launch a AgentAttachThread which will poll the flagFile
+        // until the child process is launched.
         AgentAttachThread t = new AgentAttachThread(flagFile, agentJar);
         t.start();
         return t;
@@ -225,13 +225,17 @@
                 // reason the child process fails to launch, this test will be terminated
                 // by JTREG's time-out mechanism.
                 Thread.sleep(100);
-                List<VirtualMachineDescriptor> vmds = VirtualMachine.list();
-                for (VirtualMachineDescriptor vmd : vmds) {
-                    if (vmd.displayName().contains(flagFile) && vmd.displayName().contains("InstrumentationApp")) {
-                        // We use flagFile (which has the PID of this process) as a unique identifier
-                        // to ident the child process, which we want to attach to.
-                        System.out.println("Process found: " + vmd.id() + " " + vmd.displayName());
-                        return vmd.id();
+                File f = new File(flagFile);
+                if (f.exists() && f.length() > 100) {
+                    try (FileInputStream in = new FileInputStream(f)) {
+                        Scanner scanner = new Scanner(in);
+                        return Long.toString(scanner.nextLong());
+                    } catch (Throwable t) {
+                        // This may happen on Windows if the child process has not
+                        // fully closed the output stream to the flagFile
+                        System.out.println("Ignored: " + t);
+                        t.printStackTrace(System.out);
+                        continue;
                     }
                 }
             }
@@ -240,6 +244,7 @@
         public void run() {
             try {
                 String pid = getPid(flagFile);
+                System.out.println("child pid = " + pid);
                 VirtualMachine vm = VirtualMachine.attach(pid);
                 System.out.println(agentJar);
                 vm.loadAgent(agentJar);