< prev index next >

test/hotspot/jtreg/runtime/8176717/TestInheritFD.java

second review

changes after first review

8202740: runtime/8176717/TestInheritFD.java fails with java.lang.RuntimeException: could not match: VM RESULT => RETAINS FD

0 import static java.io.File.createTempFile;                                                                                 
1 import static java.lang.Long.parseLong;                                                                                    
2 import static java.lang.System.getProperty;                                                                                
3 import static java.lang.management.ManagementFactory.getOperatingSystemMXBean;                                             
4 import static java.nio.file.Files.readAllBytes;                                                                            
                                                                                                                           
                                                                                                                           
                                                                                                                           
5 import static jdk.test.lib.process.ProcessTools.createJavaProcessBuilder;                                                  
6 
                                                                                                                           
7 import java.io.File;                                                                                                       
                                                                                                                           
                                                                                                                           
8 import java.io.IOException;                                                                                                
9                                                                                                                            
10 import com.sun.management.UnixOperatingSystemMXBean;                                                                       
                                                                                                                           
11 
12 /*                                                                                                                         
13  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.                                                  
14  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.                                                           
15  *                                                                                                                         
16  * This code is free software; you can redistribute it and/or modify it                                                    
17  * under the terms of the GNU General Public License version 2 only, as                                                    
18  * published by the Free Software Foundation.                                                                              
19  *                                                                                                                         
20  * This code is distributed in the hope that it will be useful, but WITHOUT                                                
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or                                                   
22  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License                                                   
23  * version 2 for more details (a copy is included in the LICENSE file that                                                 
24  * accompanied this code).                                                                                                 
25  *                                                                                                                         
26  * You should have received a copy of the GNU General Public License version                                               
27  * 2 along with this work; if not, write to the Free Software Foundation,                                                  
28  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.                                                           
29  *                                                                                                                         

0 import static java.io.File.createTempFile;
1 import static java.lang.Long.parseLong;
2 import static java.lang.System.getProperty;

3 import static java.nio.file.Files.readAllBytes;
4 import static java.util.Arrays.stream;
5 import static java.util.stream.Collectors.joining;
6 import static java.util.stream.Collectors.toList;
7 import static jdk.test.lib.process.ProcessTools.createJavaProcessBuilder;
8 
9 import java.io.BufferedReader;
10 import java.io.File;
11 import java.io.FileNotFoundException;
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.io.InputStreamReader;
15 import java.util.Collection;
16 import java.util.stream.Stream;
17 
18 /*
19  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
20  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21  *
22  * This code is free software; you can redistribute it and/or modify it
23  * under the terms of the GNU General Public License version 2 only, as
24  * published by the Free Software Foundation.
25  *
26  * This code is distributed in the hope that it will be useful, but WITHOUT
27  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
28  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
29  * version 2 for more details (a copy is included in the LICENSE file that
30  * accompanied this code).
31  *
32  * You should have received a copy of the GNU General Public License version
33  * 2 along with this work; if not, write to the Free Software Foundation,
34  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
35  *

39  * @library /test/lib                                                                                                      
40  * @modules java.base/jdk.internal.misc                                                                                    
41  *          java.management                                                                                                
42  */                                                                                                                        
43 
44 /**                                                                                                                        
45  * Test that HotSpot does not leak logging file descriptors.                                                               
46  *                                                                                                                         
47  * This test is performed in three steps. The first VM starts a second VM with                                             
48  * gc logging enabled. The second VM starts a third VM and redirects the third                                             
49  * VMs output to the first VM, it then exits and hopefully closes its log file.                                            
50  *                                                                                                                         
51  * The third VM waits for the second to exit and close its log file. After that,                                           
52  * the third VM tries to rename the log file of the second VM. If it succeeds in                                           
53  * doing so it means that the third VM did not inherit the open log file                                                   
54  * (windows can not rename opened files easily)                                                                            
55  *                                                                                                                         
56  * The third VM communicates the success to rename the file by printing "CLOSED                                            
57  * FD". The first VM checks that the string was printed by the third VM.                                                   
58  *                                                                                                                         
59  * On unix like systems, UnixOperatingSystemMXBean is used to check open file                                              
60  * descriptors.                                                                                                            
61  */                                                                                                                        
62 
63 public class TestInheritFD {                                                                                               
64 
65     public static final String LEAKS_FD = "VM RESULT => LEAKS FD";                                                         
66     public static final String RETAINS_FD = "VM RESULT => RETAINS FD";                                                     
67     public static final String EXIT = "VM RESULT => VM EXIT";                                                              
                                                                                                                           
68 
69     // first VM                                                                                                            
70     public static void main(String[] args) throws Exception {                                                              
71         String logPath = createTempFile("logging", ".log").getName();                                                      
72         File commFile = createTempFile("communication", ".txt");                                                           
73 
74         ProcessBuilder pb = createJavaProcessBuilder(                                                                      
75             "-Xlog:gc:\"" + logPath + "\"",                                                                                
76             "-Dtest.jdk=" + getProperty("test.jdk"),                                                                       
77             VMStartedWithLogging.class.getName(),                                                                          
78             logPath);                                                                                                      
79 
80         pb.redirectOutput(commFile); // use temp file to communicate between processes                                     
81         pb.start();                                                                                                        
82 
83         String out = "";                                                                                                   
84         do {                                                                                                               
85             out = new String(readAllBytes(commFile.toPath()));                                                             
86             Thread.sleep(100);                                                                                             
87             System.out.println("SLEEP 100 millis");                                                                        
88         } while (!out.contains(EXIT));                                                                                     
89 
90         System.out.println(out);                                                                                           
91         if (out.contains(RETAINS_FD)) {                                                                                    
92             System.out.println("Log file was not inherited by third VM");                                                  
93         } else {                                                                                                           
94             throw new RuntimeException("could not match: " + RETAINS_FD);                                                  
95         }                                                                                                                  
96     }                                                                                                                      
97 
98     static class VMStartedWithLogging {                                                                                    
99         // second VM                                                                                                       
100         public static void main(String[] args) throws IOException, InterruptedException {                                  
101             ProcessBuilder pb = createJavaProcessBuilder(                                                                  
102                 "-Dtest.jdk=" + getProperty("test.jdk"),                                                                   
103                 VMShouldNotInheritFileDescriptors.class.getName(),                                                         
104                 args[0],                                                                                                   
105                 "" + ProcessHandle.current().pid(),                                                                        
106                 "" + (supportsUnixMXBean()?+unixNrFD():-1));                                                               
107             pb.inheritIO(); // in future, redirect information from third VM to first VM                                   
108             pb.start();                                                                                                    
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
109         }                                                                                                                  
110     }                                                                                                                      
111 
112     static class VMShouldNotInheritFileDescriptors {                                                                       
113         // third VM                                                                                                        
114         public static void main(String[] args) throws InterruptedException {                                               
115             File logFile = new File(args[0]);                                                                              
116             long parentPid = parseLong(args[1]);                                                                           
117             long parentFDCount = parseLong(args[2]);                                                                       
118                                                                                                                            
119             if(supportsUnixMXBean()){                                                                                      
120                 long thisFDCount = unixNrFD();                                                                             
121                 System.out.println("This VM FD-count (" + thisFDCount + ") should be strictly less than parent VM FD-count 
122                 System.out.println(thisFDCount<parentFDCount?RETAINS_FD:LEAKS_FD);                                         
123             } else if (getProperty("os.name").toLowerCase().contains("win")) {                                             
124                 windows(logFile, parentPid);                                                                               
125             } else {                                                                                                       
126                 System.out.println(LEAKS_FD); // default fail on unknown configuration                                     
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
127             }                                                                                                              
128             System.out.println(EXIT);                                                                                      
129         }                                                                                                                  
130     }                                                                                                                      
131 
132     static boolean supportsUnixMXBean() {                                                                                  
133         return getOperatingSystemMXBean() instanceof UnixOperatingSystemMXBean;                                            
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
                                                                                                                           
134     }                                                                                                                      
135 
136     static long unixNrFD() {                                                                                               
137         UnixOperatingSystemMXBean osBean = (UnixOperatingSystemMXBean) getOperatingSystemMXBean();                         
138         return osBean.getOpenFileDescriptorCount();                                                                        
                                                                                                                           
                                                                                                                           
139     }                                                                                                                      
140 
141     static void windows(File f, long parentPid) throws InterruptedException {                                              
142         System.out.println("waiting for pid: " + parentPid);                                                               
143         ProcessHandle.of(parentPid).ifPresent(handle -> handle.onExit().join());                                           
144         System.out.println("trying to rename file to the same name: " + f);                                                
145         System.out.println(f.renameTo(f)?RETAINS_FD:LEAKS_FD); // this parts communicates a closed file descriptor by print
146     }                                                                                                                      

45  * @library /test/lib
46  * @modules java.base/jdk.internal.misc
47  *          java.management
48  */
49 
50 /**
51  * Test that HotSpot does not leak logging file descriptors.
52  *
53  * This test is performed in three steps. The first VM starts a second VM with
54  * gc logging enabled. The second VM starts a third VM and redirects the third
55  * VMs output to the first VM, it then exits and hopefully closes its log file.
56  *
57  * The third VM waits for the second to exit and close its log file. After that,
58  * the third VM tries to rename the log file of the second VM. If it succeeds in
59  * doing so it means that the third VM did not inherit the open log file
60  * (windows can not rename opened files easily)
61  *
62  * The third VM communicates the success to rename the file by printing "CLOSED
63  * FD". The first VM checks that the string was printed by the third VM.
64  *
65  * On unix like systems "lsof" or "pfiles" is used.

66  */
67 
68 public class TestInheritFD {
69 
70     public static final String LEAKS_FD = "VM RESULT => LEAKS FD";
71     public static final String RETAINS_FD = "VM RESULT => RETAINS FD";
72     public static final String EXIT = "VM RESULT => VM EXIT";
73     public static final String LOG_SUFFIX = ".strangelogsuffixthatcanbecheckedfor";
74 
75     // first VM
76     public static void main(String[] args) throws Exception {
77         String logPath = createTempFile("logging", LOG_SUFFIX).getName();
78         File commFile = createTempFile("communication", ".txt");
79 
80         ProcessBuilder pb = createJavaProcessBuilder(
81             "-Xlog:gc:\"" + logPath + "\"",
82             "-Dtest.jdk=" + getProperty("test.jdk"),
83             VMStartedWithLogging.class.getName(),
84             logPath);
85 
86         pb.redirectOutput(commFile); // use temp file to communicate between processes
87         pb.start();
88 
89         String out = "";
90         do {
91             out = new String(readAllBytes(commFile.toPath()));
92             Thread.sleep(100);
93             System.out.println("SLEEP 100 millis");
94         } while (!out.contains(EXIT));
95 
96         System.out.println(out);
97         if (out.contains(RETAINS_FD)) {
98             System.out.println("Log file was not inherited by third VM");
99         } else {
100             throw new RuntimeException("could not match: " + RETAINS_FD);
101         }
102     }
103 
104     static class VMStartedWithLogging {
105         // second VM
106         public static void main(String[] args) throws IOException, InterruptedException {
107             ProcessBuilder pb = createJavaProcessBuilder(
108                 "-Dtest.jdk=" + getProperty("test.jdk"),
109                 VMShouldNotInheritFileDescriptors.class.getName(),
110                 args[0],
111                 "" + ProcessHandle.current().pid());

112             pb.inheritIO(); // in future, redirect information from third VM to first VM
113             pb.start();
114 
115             if (getProperty("os.name").toLowerCase().contains("win") == false) {
116                 System.out.println("(Second VM) Open file descriptors:\n" + outputContainingFilenames().stream().collect(jo
117             }
118         }
119     }
120 
121     static class VMShouldNotInheritFileDescriptors {
122         // third VM
123         public static void main(String[] args) throws InterruptedException {
124             try {
125                 File logFile = new File(args[0]);
126                 long parentPid = parseLong(args[1]);
127                 fakeLeakyJVM(false); // for debugging of test case
128 
129                 if (getProperty("os.name").toLowerCase().contains("win")) {
130                     windows(logFile, parentPid);
131                 } else {
132                     Collection<String> output = outputContainingFilenames();
133                     System.out.println("(Third VM) Open file descriptors:\n" + output.stream().collect(joining("\n")));
134                     System.out.println(findOpenLogFile(output) ? LEAKS_FD : RETAINS_FD);
135                 }
136             } catch (Exception e) {
137                 System.out.println(e.toString());
138             } finally {
139                 System.out.println(EXIT);
140             }

141         }
142     }
143 
144     // for debugging of test case
145     @SuppressWarnings("resource")
146     static void fakeLeakyJVM(boolean fake) {
147         if (fake) {
148             try {
149                 new FileOutputStream("fakeLeakyJVM" + LOG_SUFFIX, false);
150             } catch (FileNotFoundException e) {
151             }
152         }
153     }
154 
155     static Stream<String> run(String... args){
156         try {
157             return new BufferedReader(new InputStreamReader(new ProcessBuilder(args).start().getInputStream())).lines();
158         } catch (IOException e) {
159             throw new RuntimeException(e);
160         }
161     }
162 
163     static Collection<String> outputContainingFilenames() {
164         long pid = ProcessHandle.current().pid();
165         String[] command = stream(new String[][]{
166                 {"/usr/bin/lsof", "-p"},
167                 {"/usr/sbin/lsof", "-p"},
168                 {"/bin/lsof", "-p"},
169                 {"/sbin/lsof", "-p"},
170                 {"/usr/bin/pfiles", "-F"}}) // Solaris
171             .filter(args -> new File(args[0]).exists())
172             .findFirst()
173             .orElseThrow(() -> new RuntimeException("could not find lsof-like command"));
174 
175         System.out.println("using command: " + command[0] + " " + command[1]);
176         return run(command[0], command[1], "" + pid).collect(toList());
177     }
178 
179     static boolean findOpenLogFile(Collection<String> fileNames) {
180         return fileNames.stream()
181             .filter(fileName -> fileName.contains(LOG_SUFFIX))
182             .findAny()
183             .isPresent();
184     }
185 
186     static void windows(File f, long parentPid) throws InterruptedException {
187         System.out.println("waiting for pid: " + parentPid);
188         ProcessHandle.of(parentPid).ifPresent(handle -> handle.onExit().join());
189         System.out.println("trying to rename file to the same name: " + f);
190         System.out.println(f.renameTo(f) ? RETAINS_FD : LEAKS_FD); // this parts communicates a closed file descriptor by p
191     }
< prev index next >