GatherProcessInfoTimeoutHandler.java revision 1870:4aa2e64eff30
1191783Srmacklem/*
2191783Srmacklem * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3191783Srmacklem * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4191783Srmacklem *
5191783Srmacklem * This code is free software; you can redistribute it and/or modify it
6191783Srmacklem * under the terms of the GNU General Public License version 2 only, as
7191783Srmacklem * published by the Free Software Foundation.
8191783Srmacklem *
9191783Srmacklem * This code is distributed in the hope that it will be useful, but WITHOUT
10191783Srmacklem * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11191783Srmacklem * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12191783Srmacklem * version 2 for more details (a copy is included in the LICENSE file that
13191783Srmacklem * accompanied this code).
14191783Srmacklem *
15191783Srmacklem * You should have received a copy of the GNU General Public License version
16191783Srmacklem * 2 along with this work; if not, write to the Free Software Foundation,
17191783Srmacklem * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18191783Srmacklem *
19191783Srmacklem * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20191783Srmacklem * or visit www.oracle.com if you need additional information or have any
21191783Srmacklem * questions.
22191783Srmacklem */
23191783Srmacklem
24191783Srmacklempackage jdk.test.failurehandler.jtreg;
25191783Srmacklem
26191783Srmacklemimport com.sun.javatest.regtest.OS;
27191783Srmacklemimport com.sun.javatest.regtest.TimeoutHandler;
28191783Srmacklemimport jdk.test.failurehandler.*;
29191783Srmacklem
30191783Srmacklemimport java.io.File;
31191783Srmacklemimport java.io.FileWriter;
32191783Srmacklemimport java.io.IOException;
33191783Srmacklemimport java.io.PrintWriter;
34191783Srmacklemimport java.lang.reflect.Field;
35191783Srmacklemimport java.nio.file.Path;
36191783Srmacklem
37191783Srmacklem/**
38191783Srmacklem * A timeout handler for jtreg, which gathers information about the timed out
39191783Srmacklem * process and its children.
40191783Srmacklem */
41191783Srmacklempublic class GatherProcessInfoTimeoutHandler extends TimeoutHandler {
42191783Srmacklem    static {
43191783Srmacklem        try {
44191783Srmacklem            System.loadLibrary("timeoutHandler");
45191783Srmacklem        } catch (UnsatisfiedLinkError ignore) {
46191783Srmacklem            // not all os need timeoutHandler native-library
47191783Srmacklem        }
48191783Srmacklem    }
49191783Srmacklem    private static final String LOG_FILENAME = "processes.log";
50191783Srmacklem    private static final String OUTPUT_FILENAME = "processes.html";
51191783Srmacklem
52191783Srmacklem    public GatherProcessInfoTimeoutHandler(PrintWriter jtregLog, File outputDir,
53191783Srmacklem                                           File testJdk) {
54191783Srmacklem        super(jtregLog, outputDir, testJdk);
55191783Srmacklem    }
56191783Srmacklem
57191783Srmacklem    /**
58191783Srmacklem     * Runs various actions for jtreg timeout handler.
59191783Srmacklem     *
60220683Srmacklem     * <p>Please see method code for the actions.
61191783Srmacklem     */
62191783Srmacklem    @Override
63191783Srmacklem    protected void runActions(Process process, long pid)
64191783Srmacklem            throws InterruptedException {
65191783Srmacklem        Path workDir = outputDir.toPath();
66191783Srmacklem
67191783Srmacklem        String name = getClass().getName();
68191783Srmacklem        PrintWriter actionsLog;
69191783Srmacklem        try {
70191783Srmacklem            // try to open a separate file for aciton log
71223280Srmacklem            actionsLog = new PrintWriter(new FileWriter(
72191783Srmacklem                    workDir.resolve(LOG_FILENAME).toFile(), true));
73191783Srmacklem        } catch (IOException e) {
74191783Srmacklem            // use jtreg log as a fallback
75191783Srmacklem            actionsLog = log;
76191783Srmacklem            actionsLog.printf("ERROR: %s cannot open log file %s : %s", name,
77191783Srmacklem                    LOG_FILENAME, e.getMessage());
78191783Srmacklem        }
79191783Srmacklem        try {
80191783Srmacklem            actionsLog.printf("%s ---%n", name);
81191783Srmacklem
82220683Srmacklem            File output = workDir.resolve(OUTPUT_FILENAME).toFile();
83220683Srmacklem            try {
84191783Srmacklem                PrintWriter pw = new PrintWriter(new FileWriter(output, true));
85191783Srmacklem                runGatherer(name, workDir, actionsLog, pw, pid);
86306609Srmacklem            } catch (IOException e) {
87191783Srmacklem                actionsLog.printf("IOException: cannot open output file[%s] : %s",
88220683Srmacklem                        output, e.getMessage());
89220683Srmacklem                e.printStackTrace(actionsLog);
90191783Srmacklem            }
91191783Srmacklem        } finally {
92191783Srmacklem            actionsLog.printf("--- %s%n", name);
93198291Sjh            // don't close jtreg log
94198291Sjh            if (actionsLog != log) {
95198291Sjh                actionsLog.close();
96198291Sjh            } else {
97191783Srmacklem                log.flush();
98191783Srmacklem            }
99191783Srmacklem        }
100191783Srmacklem    }
101191783Srmacklem
102191783Srmacklem    @Override
103191783Srmacklem    protected long getProcessId(Process process) {
104191783Srmacklem        long result = super.getProcessId(process);
105191783Srmacklem        if (result == 0L) {
106203119Srmacklem            /* jtreg didn't find pid, most probably we are on JDK < 9
107191783Srmacklem               there is no Process::getPid */
108191783Srmacklem            if ("windows".equals(OS.current().family)) {
109191783Srmacklem                try {
110191783Srmacklem                    Field field = process.getClass().getDeclaredField("handle");
111191783Srmacklem                    boolean old = field.isAccessible();
112191783Srmacklem                    try {
113191783Srmacklem                        field.setAccessible(true);
114198291Sjh                        long handle = field.getLong(process);
115198291Sjh                        result = getWin32Pid(handle);
116198291Sjh                    } finally {
117191783Srmacklem                        field.setAccessible(old);
118191783Srmacklem                    }
119191783Srmacklem                } catch (ReflectiveOperationException e) {
120191783Srmacklem                    e.printStackTrace(log);
121191783Srmacklem                }
122191783Srmacklem            }
123191783Srmacklem        }
124191783Srmacklem        return result;
125191783Srmacklem    }
126191783Srmacklem
127191783Srmacklem    private native long getWin32Pid(long handle);
128191783Srmacklem
129191783Srmacklem    private void runGatherer(String name, Path workDir, PrintWriter log,
130191783Srmacklem                             PrintWriter out, long pid) {
131191783Srmacklem        try (HtmlPage html = new HtmlPage(out)) {
132191783Srmacklem            ProcessInfoGatherer gatherer = new GathererFactory(
133191783Srmacklem                    OS.current().family,
134191783Srmacklem                    workDir, log, testJdk.toPath()).getProcessInfoGatherer();
135191783Srmacklem            try (ElapsedTimePrinter timePrinter
136191783Srmacklem                         = new ElapsedTimePrinter(new Stopwatch(), name, log)) {
137191783Srmacklem                gatherer.gatherProcessInfo(html.getRootSection(), pid);
138323142Skib            }
139323142Skib        } catch (Throwable e) {
140191783Srmacklem            log.printf("ERROR: exception in timeout handler %s:", name);
141323142Skib            e.printStackTrace(log);
142323142Skib        }
143196332Srmacklem    }
144323142Skib}
145323142Skib