001: /**
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */package com.tc.util.runtime;
005:
006: import com.tc.exception.TCRuntimeException;
007: import com.tc.process.StreamCollector;
008: import com.tc.test.TestConfigObject;
009: import com.tc.util.concurrent.ThreadUtil;
010: import com.tc.util.exception.ExceptionUtil;
011:
012: import java.io.File;
013: import java.lang.reflect.InvocationTargetException;
014: import java.lang.reflect.Method;
015:
016: public class ThreadDump {
017:
018: public static void main(String args[]) {
019: dumpThreadsOnce();
020:
021: // This flush()'ing and sleeping is a (perhaps poor) attempt at making ThreadDumpTest pass on Jrockit
022: System.err.flush();
023: System.out.flush();
024: try {
025: Thread.sleep(5000);
026: } catch (InterruptedException e) {
027: e.printStackTrace();
028: }
029: }
030:
031: public static void dumpThreadsOnce() {
032: dumpThreadsMany(1, 0L);
033: }
034:
035: public static int dumpThreadsMany(int iterations, long delay) {
036: int pid = 0;
037: RuntimeException windowsPidException = null;
038: try {
039: pid = GetPid.getPID();
040: } catch (RuntimeException re) {
041: if (Os.isWindows()) {
042: if (Vm.isIBM()) {
043: windowsPidException = re;
044: } else {
045: throw re;
046: }
047: } else {
048: System.err
049: .println("Got exception trying to get the process ID, stacktrace is below:");
050: ExceptionUtil.dumpFullStackTrace(re, System.err);
051: System.err.flush();
052: }
053: }
054:
055: for (int i = 0; i < iterations; i++) {
056: boolean doStandardDump = !Vm.isIBM();
057: if (Vm.isIBM()) {
058: try {
059: doIbmDump();
060: } catch (Exception e) {
061: System.err
062: .println("Got an exception while trying to use the native IBM thread"
063: + " dump facility, using 'standard' method. Stacktrace is below:");
064: ExceptionUtil.dumpFullStackTrace(e, System.err);
065: System.err.flush();
066: doStandardDump = true;
067: }
068: }
069: if (doStandardDump) {
070: if (pid == 0) {
071: if (Os.isWindows()) {
072: throw new TCRuntimeException(
073: "Unable to find my process ID, cannot dump threads",
074: windowsPidException);
075: } else {
076: System.err
077: .println("My PID is not available, sending QUIT signal to process group (PID 0)");
078: System.err.flush();
079: }
080: }
081: if (Os.isWindows()) {
082: doWindowsDump(pid);
083: } else {
084: doUnixDump(pid);
085: }
086: }
087: ThreadUtil.reallySleep(delay);
088: }
089:
090: return pid;
091: }
092:
093: public static void dumpProcessGroup() {
094: if (!Os.isUnix()) {
095: throw new AssertionError("unix only");
096: }
097: doUnixDump(0);
098: }
099:
100: public static void dumpProcessGroupMany(int iterations, long delay) {
101: for (int i = 0; i < iterations; i++) {
102: dumpProcessGroup();
103:
104: ThreadUtil.reallySleep(delay);
105: }
106: }
107:
108: private static void doUnixDump(int pid) {
109: doSignal(new String[] { "-QUIT" }, pid);
110: }
111:
112: private static void doWindowsDump(int pid) {
113: doSignal(new String[] {}, pid);
114: }
115:
116: private static void doIbmDump() throws ClassNotFoundException,
117: SecurityException, NoSuchMethodException,
118: IllegalArgumentException, IllegalAccessException,
119: InvocationTargetException {
120: final Class ibmDumpClass = Class.forName("com.ibm.jvm.Dump");
121: final Method ibmDumpMethod = ibmDumpClass.getDeclaredMethod(
122: "JavaDump", new Class[] {});
123: ibmDumpMethod.invoke(null, new Object[] {});
124: }
125:
126: private static void doSignal(String[] args, int pid) {
127: File program = SignalProgram.PROGRAM;
128:
129: try {
130: String[] cmd = new String[1 + args.length + 1];
131: cmd[0] = program.getAbsolutePath();
132: System.arraycopy(args, 0, cmd, 1, args.length);
133:
134: cmd[cmd.length - 1] = Integer.toString(pid);
135:
136: Process p = Runtime.getRuntime().exec(cmd);
137: p.getOutputStream().close();
138: StreamCollector err = new StreamCollector(p
139: .getErrorStream());
140: StreamCollector out = new StreamCollector(p
141: .getInputStream());
142: err.start();
143: out.start();
144:
145: p.waitFor();
146:
147: err.join();
148: out.join();
149:
150: System.err.print(err.toString());
151: System.err.flush();
152: System.out.print(out.toString());
153: System.out.flush();
154: } catch (Exception e) {
155: e.printStackTrace();
156: }
157: }
158:
159: private static class SignalProgram {
160: static final File PROGRAM;
161:
162: static {
163: PROGRAM = getSignalProgram();
164: }
165:
166: private static File getSignalProgram() {
167: File rv = null;
168:
169: if (Os.isWindows()) {
170: try {
171: rv = new File(TestConfigObject.getInstance()
172: .executableSearchPath(), "SendSignal.EXE");
173: } catch (Exception e) {
174: throw new RuntimeException(e);
175: }
176: } else {
177: File binKill = new File("/bin/kill");
178: File usrBinKill = new File("/usr/bin/kill");
179:
180: if (binKill.exists()) {
181: rv = binKill;
182: } else if (usrBinKill.exists()) {
183: rv = usrBinKill;
184: }
185: }
186:
187: if (rv != null) {
188: if (rv.exists() && rv.isFile()) {
189: return rv;
190: }
191: System.err.println("Cannot find signal program: "
192: + rv.getAbsolutePath());
193: System.err.flush();
194: }
195:
196: throw new RuntimeException("Cannot find signal program");
197: }
198: }
199: }
|