GatherProcessInfoTimeoutHandler.java revision 2249:3803b441db32
1/* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24package jdk.test.failurehandler.jtreg; 25 26import com.sun.javatest.regtest.TimeoutHandler; 27import jdk.test.failurehandler.*; 28 29import java.io.File; 30import java.io.FileWriter; 31import java.io.IOException; 32import java.io.PrintWriter; 33import java.lang.reflect.Field; 34import java.nio.file.Path; 35 36/** 37 * A timeout handler for jtreg, which gathers information about the timed out 38 * process and its children. 39 */ 40public class GatherProcessInfoTimeoutHandler extends TimeoutHandler { 41 private static final boolean HAS_NATIVE_LIBRARY; 42 static { 43 boolean value = true; 44 try { 45 System.loadLibrary("timeoutHandler"); 46 } catch (UnsatisfiedLinkError ignore) { 47 // not all os need timeoutHandler native-library 48 value = false; 49 } 50 HAS_NATIVE_LIBRARY = value; 51 } 52 private static final String LOG_FILENAME = "processes.log"; 53 private static final String OUTPUT_FILENAME = "processes.html"; 54 55 public GatherProcessInfoTimeoutHandler(PrintWriter jtregLog, File outputDir, 56 File testJdk) { 57 super(jtregLog, outputDir, testJdk); 58 } 59 60 /** 61 * Runs various actions for jtreg timeout handler. 62 * 63 * <p>Please see method code for the actions. 64 */ 65 @Override 66 protected void runActions(Process process, long pid) 67 throws InterruptedException { 68 Path workDir = outputDir.toPath(); 69 70 String name = getClass().getName(); 71 PrintWriter actionsLog; 72 try { 73 // try to open a separate file for aciton log 74 actionsLog = new PrintWriter(new FileWriter( 75 workDir.resolve(LOG_FILENAME).toFile(), true)); 76 } catch (IOException e) { 77 // use jtreg log as a fallback 78 actionsLog = log; 79 actionsLog.printf("ERROR: %s cannot open log file %s : %s", name, 80 LOG_FILENAME, e.getMessage()); 81 } 82 try { 83 actionsLog.printf("%s ---%n", name); 84 85 File output = workDir.resolve(OUTPUT_FILENAME).toFile(); 86 try { 87 PrintWriter pw = new PrintWriter(new FileWriter(output, true)); 88 runGatherer(name, workDir, actionsLog, pw, pid); 89 } catch (IOException e) { 90 actionsLog.printf("IOException: cannot open output file[%s] : %s", 91 output, e.getMessage()); 92 e.printStackTrace(actionsLog); 93 } 94 } finally { 95 actionsLog.printf("--- %s%n", name); 96 // don't close jtreg log 97 if (actionsLog != log) { 98 actionsLog.close(); 99 } else { 100 log.flush(); 101 } 102 } 103 } 104 105 @Override 106 protected long getProcessId(Process process) { 107 long result = super.getProcessId(process); 108 if (result == 0L) { 109 /* jtreg didn't find pid, most probably we are on JDK < 9 110 there is no Process::getPid */ 111 if (HAS_NATIVE_LIBRARY && "windows".equals(OS.current().family)) { 112 try { 113 Field field = process.getClass().getDeclaredField("handle"); 114 boolean old = field.isAccessible(); 115 try { 116 field.setAccessible(true); 117 long handle = field.getLong(process); 118 result = getWin32Pid(handle); 119 } finally { 120 field.setAccessible(old); 121 } 122 } catch (ReflectiveOperationException e) { 123 e.printStackTrace(log); 124 } 125 } 126 } 127 return result; 128 } 129 130 private native long getWin32Pid(long handle); 131 132 private void runGatherer(String name, Path workDir, PrintWriter log, 133 PrintWriter out, long pid) { 134 try (HtmlPage html = new HtmlPage(out)) { 135 ProcessInfoGatherer gatherer = new GathererFactory( 136 OS.current().family, 137 workDir, log, testJdk.toPath()).getProcessInfoGatherer(); 138 try (ElapsedTimePrinter timePrinter 139 = new ElapsedTimePrinter(new Stopwatch(), name, log)) { 140 gatherer.gatherProcessInfo(html.getRootSection(), pid); 141 } 142 } catch (Throwable e) { 143 log.printf("ERROR: exception in timeout handler %s:", name); 144 e.printStackTrace(log); 145 } 146 } 147} 148