< prev index next >

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

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  *                                                                                                                         
30  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA                                                 
31  * or visit www.oracle.com if you need additional information or have any                                                  
32  * questions.                                                                                                              
33  */                                                                                                                        
34 
35 /*                                                                                                                         
36  * @test TestInheritFD                                                                                                     
37  * @bug 8176717 8176809                                                                                                    
38  * @summary a new process should not inherit open file descriptors                                                         
                                                                                                                           
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     }                                                                                                                      

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 java.nio.file.Files.readSymbolicLink;
6 import static java.util.Arrays.stream;
7 import static java.util.Optional.empty;
8 import static java.util.Optional.of;
9 import static java.util.stream.Collectors.joining;
10 import static jdk.test.lib.process.ProcessTools.createJavaProcessBuilder;
11 
12 import java.io.File;
13 import java.io.FileNotFoundException;
14 import java.io.FileOutputStream;
15 import java.io.IOException;
16 import java.util.Optional;
17 
18 import com.sun.management.UnixOperatingSystemMXBean;
19 
20 /*
21  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
22  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
23  *
24  * This code is free software; you can redistribute it and/or modify it
25  * under the terms of the GNU General Public License version 2 only, as
26  * published by the Free Software Foundation.
27  *
28  * This code is distributed in the hope that it will be useful, but WITHOUT
29  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
30  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
31  * version 2 for more details (a copy is included in the LICENSE file that
32  * accompanied this code).
33  *
34  * You should have received a copy of the GNU General Public License version
35  * 2 along with this work; if not, write to the Free Software Foundation,
36  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
37  *
38  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
39  * or visit www.oracle.com if you need additional information or have any
40  * questions.
41  */
42 
43 /*
44  * @test TestInheritFD
45  * @bug 8176717 8176809
46  * @summary a new process should not inherit open file descriptors
47  * @requires (os.family != "mac")
48  * @library /test/lib
49  * @modules java.base/jdk.internal.misc
50  *          java.management
51  */
52 
53 /**
54  * Test that HotSpot does not leak logging file descriptors.
55  *
56  * This test is performed in three steps. The first VM starts a second VM with
57  * gc logging enabled. The second VM starts a third VM and redirects the third
58  * VMs output to the first VM, it then exits and hopefully closes its log file.
59  *
60  * The third VM waits for the second to exit and close its log file. After that,
61  * the third VM tries to rename the log file of the second VM. If it succeeds in
62  * doing so it means that the third VM did not inherit the open log file
63  * (windows can not rename opened files easily)
64  *
65  * The third VM communicates the success to rename the file by printing "CLOSED
66  * FD". The first VM checks that the string was printed by the third VM.
67  *
68  * On unix like systems, UnixOperatingSystemMXBean is used to check open file
69  * descriptors.
70  */
71 
72 public class TestInheritFD {
73 
74     public static final String LEAKS_FD = "VM RESULT => LEAKS FD";
75     public static final String RETAINS_FD = "VM RESULT => RETAINS FD";
76     public static final String EXIT = "VM RESULT => VM EXIT";
77     public static final String LOG_SUFFIX = ".strangelogsuffixthatcanbecheckedfor";
78 
79     // first VM
80     public static void main(String[] args) throws Exception {
81         String logPath = createTempFile("logging", LOG_SUFFIX).getName();
82         File commFile = createTempFile("communication", ".txt");
83 
84         ProcessBuilder pb = createJavaProcessBuilder(
85             "-Xlog:gc:\"" + logPath + "\"",
86             "-Dtest.jdk=" + getProperty("test.jdk"),
87             VMStartedWithLogging.class.getName(),
88             logPath);
89 
90         pb.redirectOutput(commFile); // use temp file to communicate between processes
91         pb.start();
92 
93         String out = "";
94         do {
95             out = new String(readAllBytes(commFile.toPath()));
96             Thread.sleep(100);
97             System.out.println("SLEEP 100 millis");
98         } while (!out.contains(EXIT));
99 
100         System.out.println(out);
101         if (out.contains(RETAINS_FD)) {
102             System.out.println("Log file was not inherited by third VM");
103         } else {
104             throw new RuntimeException("could not match: " + RETAINS_FD);
105         }
106     }
107 
108     static class VMStartedWithLogging {
109         // second VM
110         public static void main(String[] args) throws IOException, InterruptedException {
111             ProcessBuilder pb = createJavaProcessBuilder(
112                 "-Dtest.jdk=" + getProperty("test.jdk"),
113                 VMShouldNotInheritFileDescriptors.class.getName(),
114                 args[0],
115                 "" + ProcessHandle.current().pid(),
116                 "" + (supportsUnixMXBean()?+unixNrFD():-1));
117             pb.inheritIO(); // in future, redirect information from third VM to first VM
118             pb.start();
119 
120             findOpenLogFile();
121         }
122     }
123 
124     static class VMShouldNotInheritFileDescriptors {
125         // third VM
126         public static void main(String[] args) throws InterruptedException {
127             File logFile = new File(args[0]);
128             long parentPid = parseLong(args[1]);
129             long parentFDCount = parseLong(args[2]);
130 
131             fakeLeakyJVM(false);
132 
133             if(supportsUnixMXBean()){
134                 long thisFDCount = unixNrFD();
135                 System.out.println("This VM FD-count ("
136                         + thisFDCount
137                         + ") should be strictly less than parent VM FD-count ("
138                         + parentFDCount
139                         + ") as log file should have been closed, HOWEVER, THIS CAN NOT BE RELIED"
140                         + " ON as files in /proc and /sys are opened by the JVM");
141                 System.out.println(findOpenLogFile() ? LEAKS_FD : RETAINS_FD);
142             } else if (getProperty("os.name").toLowerCase().contains("win")) {
143                 windows(logFile, parentPid);
144             } else {
145                 System.out.println(LEAKS_FD); // default fail on unknown configuration
146             }
147             System.out.println(EXIT);
148         }
149     }
150 
151     static boolean supportsUnixMXBean() {
152         return getOperatingSystemMXBean() instanceof UnixOperatingSystemMXBean;
153     }
154 
155     static long unixNrFD() {
156         UnixOperatingSystemMXBean osBean = (UnixOperatingSystemMXBean) getOperatingSystemMXBean();
157         return osBean.getOpenFileDescriptorCount();
158     }
159 
160     static Optional<String> linkTargetName(File f) {
161         try {
162             return of(readSymbolicLink(f.toPath()).toFile().getName());
163         } catch (IOException e) {
164             return empty();
165         }
166     }
167 
168     @SuppressWarnings("resource")
169     static void fakeLeakyJVM(boolean fake) {
170         if (fake) {
171             try {
172                 new FileOutputStream("fakeLeakyJVM" + LOG_SUFFIX, false);
173             } catch (FileNotFoundException e) {
174             }
175         }
176     }
177 
178     static boolean findOpenLogFile() {
179         File dir = new File("/proc/self/fd");
180 
181         System.out.println("Open file descriptors:\n" + stream(dir.listFiles())
182             .map(f -> f.getAbsolutePath() + " maps to: " + linkTargetName(f).orElse("?"))
183             .collect(joining("\n")));
184 
185         return stream(dir.listFiles())
186             .map(TestInheritFD::linkTargetName)
187             .flatMap(Optional::stream)
188             .filter(fileName -> fileName.endsWith(LOG_SUFFIX))
189             .findAny()
190             .isPresent();
191     }
192 
193     static void windows(File f, long parentPid) throws InterruptedException {
194         System.out.println("waiting for pid: " + parentPid);
195         ProcessHandle.of(parentPid).ifPresent(handle -> handle.onExit().join());
196         System.out.println("trying to rename file to the same name: " + f);
197         System.out.println(f.renameTo(f) ? RETAINS_FD : LEAKS_FD); // this parts communicates a closed file descriptor by p
198     }
< prev index next >