From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4310 invoked by alias); 30 Nov 2007 10:00:31 -0000 Received: (qmail 4268 invoked by uid 9697); 30 Nov 2007 10:00:29 -0000 Date: Fri, 30 Nov 2007 10:00:00 -0000 Message-ID: <20071130100029.4253.qmail@sourceware.org> From: pmachata@sourceware.org To: frysk-cvs@sourceware.org Subject: [SCM] master: Flush buffer in ftrace reporter X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: c59164dcf19440dca54e74fb4ab6297c8a58e617 X-Git-Newrev: 480e607f47241817fb2d52a7a52054475926056e Mailing-List: contact frysk-cvs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: frysk-cvs-owner@sourceware.org Reply-To: frysk@sourceware.org X-SW-Source: 2007-q4/txt/msg00501.txt.bz2 The branch, master has been updated via 480e607f47241817fb2d52a7a52054475926056e (commit) via 341fa1d918982452273754e906b66c02586e4e4c (commit) via ec7bceb4ba8f8788929353cc9a1473483d7b5dc2 (commit) via 9d20260f04cbc73d4b3116082fbf251e71e15c51 (commit) via c8aa5b7ce90892eb0ac59b3bf50b317f7c59cef9 (commit) via b940b67773f17227aa22a4c448522b6619ba95fb (commit) via c71c1e27fe9660c2c24b298f70db5b505a274898 (commit) via 084951bcda69885b1fe674dda125dc5f8e218e70 (commit) via 6e516c9e16f057e934026454511d303b25ee94d5 (commit) via e02e86f3af06c5ff1f1cffa39875ab1852a1fb9e (commit) via 34d63ec38dedba6d16ad9c4cab9e10076d3084af (commit) via 36cbd733ea2e60a15d23f0a653a646003d026e40 (commit) via 523ecb6b68531a6991380e5b6ce5fff3469db69a (commit) from c59164dcf19440dca54e74fb4ab6297c8a58e617 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 480e607f47241817fb2d52a7a52054475926056e Author: Petr Machata Date: Thu Nov 22 20:37:29 2007 +0100 Flush buffer in ftrace reporter * This prevented ftrace testsuite from passing. commit 341fa1d918982452273754e906b66c02586e4e4c Author: Petr Machata Date: Thu Nov 22 17:52:58 2007 +0100 Return values of syscalls are back * This is probably the last feature of ftrace broken by recent merger. commit ec7bceb4ba8f8788929353cc9a1473483d7b5dc2 Author: Petr Machata Date: Thu Nov 22 16:30:46 2007 +0100 Killed SyscallHandler abstraction * ... because right now it's unused, and should someone want to write Ftrace "plugins", the interface wouldn't be of much use anyway. commit 9d20260f04cbc73d4b3116082fbf251e71e15c51 Author: Petr Machata Date: Thu Nov 22 15:58:02 2007 +0100 System call parameters are back. * Syscall.java now provides interfaces that extract array of parameters from given Task. Printing methods have been changed to use them internally. Currently the extraction methods answer pre-formatted Strings. In future, it would be ideal to answer real "typed" values, even though for system calls the typing will be primitive. * Ftrace.java uses the new interfaces to obtain vector of arguments for Reporter class. commit c8aa5b7ce90892eb0ac59b3bf50b317f7c59cef9 Author: Petr Machata Date: Wed Nov 21 17:15:26 2007 +0100 Stack tracing on symbols is back commit b940b67773f17227aa22a4c448522b6619ba95fb Author: Petr Machata Date: Wed Nov 21 16:10:34 2007 +0100 Fix ftrace over fork * ftrace now blocks the forked task to give the tasksObserver a chance to pick new task up. * Pattern was changed in TestFtrace, to grab formatting changes introduced recently. commit c71c1e27fe9660c2c24b298f70db5b505a274898 Author: Petr Machata Date: Tue Nov 20 22:28:45 2007 +0100 Support INTERP metasoname. * You can use INTERP as a soname with the meaning of "interpreter of base binary". Useful for dynamic linker tracing, or suppressing thereof. * To support this feature, ObjectFile can now answer canonical name of its interp. * This new feature of ObjectFile is used in MappingGuard. commit 084951bcda69885b1fe674dda125dc5f8e218e70 Author: Petr Machata Date: Tue Nov 20 21:49:31 2007 +0100 More work on ftrace/ltrace merger. * Beware of breaking changes, testsuite will fail horribly! * Ftrace now internally uses the same reporting infrastructure as Ltrace used to. * More stuff brought over from frysk.util, that was left over before. * Changed formatting of the messages to be more stracish. Ugly tags may still come back, they stand out more clearly. * Lost the ability to write simple in-frysk plugins, as SyscallHandler is not currently supported. commit 6e516c9e16f057e934026454511d303b25ee94d5 Author: Petr Machata Date: Tue Nov 20 19:04:40 2007 +0100 Switches for syscall and mmap tracing in ftrace. * It's now possible to request to NOT trace syscalls in ftrace, with -S option. Nicer solution would leave syscalls off by default and only turn them on when requested, but that needs some discussion. * Also it's now necessary to explicitly request mmap/unmap tracing. Right now these are traced always (we need this for correct breakpoint population/evacuation), and -m option only changes whether the event is printed. commit e02e86f3af06c5ff1f1cffa39875ab1852a1fb9e Author: Petr Machata Date: Tue Nov 20 15:05:34 2007 +0100 Ltrace uses 1:1 observer:observable relationship. * This simplifies some things, and will very likely result in some performance improvements, as various object don't have to be looked up in dictionaries as often as they used to be. * Some things, e.g. synchronized methods, are probably not necessary anymore, but these are not addressed in this patch. commit 34d63ec38dedba6d16ad9c4cab9e10076d3084af Author: Petr Machata Date: Tue Nov 20 13:19:07 2007 +0100 Cleanups * Renamed LtraceObserver to FunctionObserver for consistency with observer naming elsewhere in Frysk. * Ftrace now creates one MyFunctionObserver per task, which greatly simplifies reporting. Other than that it is also probably more memory conservative and faster, because we get rid of Task lookup in hash map. commit 36cbd733ea2e60a15d23f0a653a646003d026e40 Author: Petr Machata Date: Tue Nov 20 09:33:02 2007 +0100 Fix unmapping non-ELF files commit 523ecb6b68531a6991380e5b6ce5fff3469db69a Author: Petr Machata Date: Mon Nov 19 19:10:45 2007 +0100 ftrace/ltrace merger in progress. * Ltrace and MappingGuard now implement proper addedTo/addFailed semantics, and also /should/ implement proper blocking semantics when the returned action is Action.BLOCK. That latter is not tested though. There is some duplication of code, furthrer refactoring will be necessary. * Ftrace brought over from util to ftrace package. * fltrace killed, relevant sections from man page brought over to ftrace.xml. ----------------------------------------------------------------------- Summary of changes: frysk-core/frysk/bindir/ChangeLog | 52 +- frysk-core/frysk/bindir/TestFtrace.java | 8 +- frysk-core/frysk/bindir/fltrace.java | 651 ----------- frysk-core/frysk/bindir/fltrace.xml | 254 ----- frysk-core/frysk/bindir/ftrace.java | 355 ++++++- frysk-core/frysk/bindir/ftrace.xml | 165 +++- frysk-core/frysk/ftrace/ChangeLog | 125 ++ frysk-core/frysk/ftrace/Ftrace.java | 489 ++++++++ .../{LtraceObserver.java => FunctionObserver.java} | 30 +- frysk-core/frysk/ftrace/Ltrace.java | 1197 +++++++------------- frysk-core/frysk/ftrace/MappingGuard.java | 96 ++- frysk-core/frysk/ftrace/ObjectFile.java | 18 + frysk-core/frysk/ftrace/Reporter.java | 188 +++ frysk-core/frysk/ftrace/TestLtrace.java | 165 ++-- frysk-core/frysk/proc/ChangeLog | 15 + frysk-core/frysk/proc/Syscall.java | 154 ++-- frysk-core/frysk/util/ChangeLog | 11 +- frysk-core/frysk/util/Ftrace.java | 368 ------ frysk-core/frysk/util/StracePrinter.java | 99 -- frysk-core/frysk/util/SyscallHandler.java | 48 - 20 files changed, 2067 insertions(+), 2421 deletions(-) delete mode 100644 frysk-core/frysk/bindir/fltrace.java delete mode 100644 frysk-core/frysk/bindir/fltrace.xml create mode 100644 frysk-core/frysk/ftrace/Ftrace.java rename frysk-core/frysk/ftrace/{LtraceObserver.java => FunctionObserver.java} (75%) create mode 100644 frysk-core/frysk/ftrace/Reporter.java delete mode 100644 frysk-core/frysk/util/Ftrace.java delete mode 100644 frysk-core/frysk/util/StracePrinter.java delete mode 100644 frysk-core/frysk/util/SyscallHandler.java First 500 lines of diff: diff --git a/frysk-core/frysk/bindir/ChangeLog b/frysk-core/frysk/bindir/ChangeLog index 4ad0a65..1a693b9 100644 --- a/frysk-core/frysk/bindir/ChangeLog +++ b/frysk-core/frysk/bindir/ChangeLog @@ -28,6 +28,10 @@ * TestFstack.java (testBackTraceWithDashN()) (testBackTraceWithDashNDashA()): Mark as unresolved, bug 5394. +2007-11-22 Petr Machata + + * ftrace.java: Don't set up enter/exit handlers of Ftrace. + 2007-11-21 Sami Wagiaalla * TestFstack.java (testBackTraceWithDashN): New test. @@ -35,12 +39,58 @@ * fstack.java (Stacker.Stacker): Added number-of-frames option and handling. -2007-11-20 Sami Wagiaalla +2007-11-21 Petr Machata + + * ftrace.java + (MyController): renamed to MyLtraceController. Now implements + Ftrace.StackTracedSymbolsProvider. + (MyLtraceController.symbolsStackTraceSet): New field. + (MyLtraceController.shouldStackTraceOn): New method. +2007-11-21 Petr Machata + + * TestFtrace.java: Change pattern in fork test. + +2007-11-20 Sami Wagiaalla + * TestFstack.java (testBackTraceWithDashC): Removed check for param values. (testBackTraceWithDashA): Ditto. +2007-11-20 Petr Machata + + * ftrace.java: Patterns now recognize "INTERP" meta-soname. + (MyController.isInterpOf): New method. + * ftrace.xml: Documented the same. + +2007-11-20 Petr Machata + + * ftrace.java (fltrace.addOptions): Recognize -m and -S. + + * Ftrace.java + (traceSyscalls, traceMmapUnmap): New fields. + (setDontTraceSyscalls): New method. + (setTraceMmaps): New method. + (observationCounters): New field. + (observationRequested, observationRealized): New methods. + (handleTask): Rewritten to support new options. + (FunctionObserver.addedTo): call observationRealized. + (SyscallObserver.addedTo): call observationRealized. + (ForkedObserver.addedTo): call observationRealized. + +2007-11-19 Petr Machata + + * fltrace.java: Deleted. + * fltrace.xml: Deleted. + * ftrace.java + (WorkingSetRule): Moved from fltrace.java + (MyController): Dtto. + (ftrace.*Rules): Dtto. + (ftrace.parseRules): Dtto. + (ftrace.addOptions): Recognize -plt, -dyn, -sym. + (ftrace.main): Apply -plt, -dyn, -sym. + * ftrace.xml: Parts moved over from fltrace.xml here. + 2007-11-19 Phil Muldoon * TestFhd.java (testHpdCore): Remove unresolved. diff --git a/frysk-core/frysk/bindir/TestFtrace.java b/frysk-core/frysk/bindir/TestFtrace.java index f726681..0d095ec 100644 --- a/frysk-core/frysk/bindir/TestFtrace.java +++ b/frysk-core/frysk/bindir/TestFtrace.java @@ -65,7 +65,7 @@ public class TestFtrace Config.getBinFile("ftrace").getAbsolutePath(), ""+task.getProc().getPid() }); - expect.expect(""+task.getProc().getPid()+"."+ task.getTid()); + expect.expect(""+task.getProc().getPid()+"."+ task.getTid() + " attached"); } public void testFtraceTracesExecutables () { @@ -103,12 +103,12 @@ public class TestFtrace "-c", ""+task.getProc().getPid() }); - expect.expect(""+task.getProc().getPid()+"."+ task.getTid() + " rt_sigsuspend ()"); + expect.expect(""+task.getProc().getPid()+"."+ task.getTid() + " * syscall * rt_sigsuspend"); child.assertSendAddForkWaitForAcks(); expect.expect("rt_sigsuspend"); - expect.expect("rt_sigsuspend"); + expect.expect("rt_sigsuspend"); } - + public void testFtraceHandlesPrcoessNotFound() { expect = new Expect(new String[] { Config.getBinFile("ftrace").getAbsolutePath(), diff --git a/frysk-core/frysk/bindir/fltrace.java b/frysk-core/frysk/bindir/fltrace.java deleted file mode 100644 index 36ac581..0000000 --- a/frysk-core/frysk/bindir/fltrace.java +++ /dev/null @@ -1,651 +0,0 @@ -// This file is part of the program FRYSK. -// -// Copyright 2007, Red Hat Inc. -// -// FRYSK is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License as published by -// the Free Software Foundation; version 2 of the License. -// -// FRYSK is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with FRYSK; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -// -// In addition, as a special exception, Red Hat, Inc. gives You the -// additional right to link the code of FRYSK with code not covered -// under the GNU General Public License ("Non-GPL Code") and to -// distribute linked combinations including the two, subject to the -// limitations in this paragraph. Non-GPL Code permitted under this -// exception must only link to the code of FRYSK through those well -// defined interfaces identified in the file named EXCEPTION found in -// the source code files (the "Approved Interfaces"). The files of -// Non-GPL Code may instantiate templates or use macros or inline -// functions from the Approved Interfaces without causing the -// resulting work to be covered by the GNU General Public -// License. Only Red Hat, Inc. may make changes or additions to the -// list of Approved Interfaces. You must obey the GNU General Public -// License in all respects for all of the FRYSK code and other code -// used in conjunction with FRYSK except the Non-GPL Code covered by -// this exception. If you modify this file, you may extend this -// exception to your version of the file, but you are not obligated to -// do so. If you do not wish to provide this exception without -// modification, you must delete this exception statement from your -// version and license this file solely under the GPL without -// exception. - -package frysk.bindir; - -import java.util.*; -import java.util.logging.*; -import java.util.regex.*; -import java.io.File; -import inua.util.PrintWriter; - -import gnu.classpath.tools.getopt.*; - -import frysk.proc.*; -import frysk.sys.Sig; -import frysk.util.CommandlineParser; -import frysk.stack.*; -import lib.dwfl.ElfSymbolVersion; - -import frysk.ftrace.*; - -public class fltrace -{ - protected static final Logger logger = Logger.getLogger("frysk"); - - // The command to execute - static String[] command; - - // The process id to trace - static int pid; - - // Command and arguments to exec. - ArrayList commandAndArguments; - - // True if a PID was requested. - boolean requestedPid; - - //Where to send output. - PrintWriter writer; - - class WorkingSetRule { - final public boolean addition; - final public boolean stackTrace; - - /** - * Object that performs a pattern matching of symbol - * name. null for "anything" matcher. - */ - final public Pattern namePattern; - - /** See namePattern */ - final public Pattern sonamePattern, versionPattern; - - public WorkingSetRule(boolean addition, boolean stackTrace, String nameRe, String sonameRe, String versionRe) { - this.addition = addition; - this.stackTrace = stackTrace; - this.namePattern = Pattern.compile((nameRe != null) ? nameRe : ".*"); - this.sonamePattern = Pattern.compile((sonameRe != null) ? sonameRe : ".*"); - this.versionPattern = Pattern.compile((versionRe != null) ? versionRe : ".*"); - } - - public String toString() { - return "" - + (this.addition ? "" : "-") - + (this.stackTrace ? "#" : "") - + this.namePattern.pattern() - + "@" + this.sonamePattern.pattern() - + "@@" + this.versionPattern.pattern(); - } - } - - interface LtraceControllerObserver - { - void shouldStackTraceOn(Set symbols); - } - - class MyController - implements LtraceController - { - // ArrayList - private final List pltRules = new ArrayList(); - private final List dynRules = new ArrayList(); - private final List symRules = new ArrayList(); - private final LtraceControllerObserver observer; - - public MyController(LtraceControllerObserver observer) - { - this.observer = observer; - } - - public void gotPltRules(List rules) { - logger.log(Level.FINER, "Got " + rules.size() + " PLT rules."); - this.pltRules.addAll(rules); - } - - public void gotDynRules(List rules) { - logger.log(Level.FINER, "Got " + rules.size() + " DYNAMIC rules."); - this.dynRules.addAll(rules); - } - - public void gotSymRules(List rules) { - logger.log(Level.FINER, "Got " + rules.size() + " SYMTAB rules."); - this.symRules.addAll(rules); - } - - private boolean checkVersionMatches(final TracePoint tp, final WorkingSetRule rule) - { - ElfSymbolVersion[] vers = (tp.origin == TracePointOrigin.PLT) - ? (ElfSymbolVersion[])tp.symbol.verneeds - : (ElfSymbolVersion[])tp.symbol.verdefs; - - // When there is no version assigned to symbol, we pretend it has - // a version of ''. Otherwise we require one of the versions to - // match the version pattern. - if (vers.length == 0) { - if (rule.versionPattern.matcher("").matches()) { - logger.log(Level.FINE, rule + ": `" + tp.symbol.name - + "' version match, no version."); - return true; - } - } - else - for (int i = 0; i < vers.length; ++i) - if (rule.versionPattern.matcher(vers[i].name).matches()) { - logger.log(Level.FINE, rule + ": `" + tp.symbol.name - + "' version match `" + vers[i].name+ "'."); - return true; - } - - return false; - } - - public void applyTracingRules(final Task task, final ObjectFile objf, final Ltrace.Driver driver, - final List rules, final TracePointOrigin origin) - throws lib.dwfl.ElfException - { - logger.log(Level.FINER, "Building working set for origin " + origin + "."); - - // Skip the set if it's empty... - if (rules.isEmpty()) - return; - - // Set, all tracepoints in objfile. - final Set candidates = new HashSet(); - // Set, incrementally built working set. - final Set workingSet = new HashSet(); - // Set, incrementally built set of tracepoints - // that should stacktrace. - final Set stackTraceSet = new HashSet(); - boolean candidatesInited = false; - - // Loop through all the rules, and use them to build - // workingSet from candidates. Candidates are initialized - // lazily inside the loop. - for (Iterator it = rules.iterator(); it.hasNext(); ) { - final WorkingSetRule rule = (WorkingSetRule)it.next(); - logger.log(Level.FINEST, "Considering rule " + rule + "."); - - // MAIN is meta-soname meaning "main executable". - if ((rule.sonamePattern.pattern().equals("MAIN") - && task.getProc().getExe().equals(objf.getFilename().getPath())) - || rule.sonamePattern.matcher(objf.getSoname()).matches()) - { - if (!candidatesInited) { - candidatesInited = true; - objf.eachTracePoint(new ObjectFile.TracePointIterator() { - public void tracePoint(TracePoint tp) { - if (candidates.add(tp)) - logger.log(Level.FINE, "candidate `" + tp.symbol.name + "'."); - } - }, origin); - } - - if (rule.addition) - // For '+' rules iterate over candidates, - // and add what matches to workingSet, and - // maybe to stackTraceSet. - for (Iterator jt = candidates.iterator(); jt.hasNext(); ) { - TracePoint tp = (TracePoint)jt.next(); - if (rule.namePattern.matcher(tp.symbol.name).matches() - && checkVersionMatches(tp, rule)) - { - if (workingSet.add(tp)) - logger.log(Level.CONFIG, rule + ": add `" + tp.symbol.name + "'."); - if (rule.stackTrace - && stackTraceSet.add(tp)) - logger.log(Level.CONFIG, rule + ": stack trace on `" + tp.symbol.name + "'."); - } - } - else { - // For '-' or '-#' rules iterate over - // workingSet or stackTraceSet, and remove - // what matches. - Set iterateOver = rule.stackTrace ? stackTraceSet : workingSet; - for (Iterator jt = iterateOver.iterator(); jt.hasNext(); ) { - TracePoint tp = (TracePoint)jt.next(); - if (rule.namePattern.matcher(tp.symbol.name).matches() - && checkVersionMatches(tp, rule)) { - jt.remove(); - if (!rule.stackTrace) - stackTraceSet.remove(tp); - logger.log(Level.CONFIG, rule + ": remove `" + tp.symbol.name + "'."); - } - } - } - } - } - - // Finally, apply constructed working set. - logger.log(Level.FINER, "Applying working set for origin " + origin + "."); - for (Iterator it = workingSet.iterator(); it.hasNext(); ) - driver.tracePoint(task, (TracePoint)it.next()); - - // And warn our console front end that it should stack - // trace if it sees one of these... - HashSet stackTraceSymbols = new HashSet(); - for (Iterator it = stackTraceSet.iterator(); it.hasNext(); ) - stackTraceSymbols.add(((TracePoint)it.next()).symbol); - observer.shouldStackTraceOn(stackTraceSymbols); - } - - public void fileMapped(final Task task, final ObjectFile objf, final Ltrace.Driver driver) { - try { - applyTracingRules(task, objf, driver, pltRules, TracePointOrigin.PLT); - applyTracingRules(task, objf, driver, dynRules, TracePointOrigin.DYNAMIC); - applyTracingRules(task, objf, driver, symRules, TracePointOrigin.SYMTAB); - } - catch (lib.dwfl.ElfException ee) { - ee.printStackTrace(); - } - } - } - - class MyLtraceObserver - implements LtraceObserver, - LtraceControllerObserver - { - private Map levelMap = new HashMap(); - - // Which system calls should yield a stack trace. - private HashSet syscallStackTraceSet = null; - - // Which symbols should yield a stack trace. - private HashSet symbolsStackTraceSet = new HashSet(); - - public synchronized void shouldStackTraceOn(Set symbols) - { - symbolsStackTraceSet.addAll(symbols); - } - - private Object lastItem = null; - private Task lastTask = null; - - private int getLevel(Task task) - { - int level = 0; - Integer l = (Integer)levelMap.get(task); - if (l != null) - level = l.intValue(); - return level; - } - - private void setLevel(Task task, int level) - { - levelMap.put(task, new Integer(level)); - } - - private boolean lineOpened() - { - return lastItem != null; - } - - private boolean myLineOpened(Task task, Object item) - { - return lastItem == item && lastTask == task; - } - - private void updateOpenLine(Task task, Object item) - { - lastItem = item; - lastTask = task; - } - - private String repeat(char c, int count) - { - // by Stephen Friedrich - char[] fill = new char[count]; - Arrays.fill(fill, c); - return new String(fill); - } - - private String pidInfo(Task task) - { - return "[" + task.getProc().getPid() + "." + task.getTid() + "]"; - } - - private void eventEntry(Task task, Object item, String eventType, - String eventName, Object[] args) - { - int level = this.getLevel(task); - String spaces = repeat(' ', level); - this.setLevel(task, ++level); - - if (lineOpened()) - System.err.println('\\'); - - System.err.print(pidInfo(task) + " " - + spaces + eventType + " "); - System.err.print(eventName + "("); - for (int i = 0; i < args.length; ++i) { - System.err.print(i > 0 ? ", " : ""); - // Temporary hack to get proper formatting before - // something more sane lands. - if (args[i] instanceof Long) - System.err.print("0x" + Long.toHexString(((Long)args[i]).longValue())); - else if (args[i] instanceof Integer) - System.err.print("0x" + Integer.toHexString(((Integer)args[i]).intValue())); - else - System.err.print(args[i]); - } - System.err.print(")"); - - updateOpenLine(task, item); - } - - private void eventLeave(Task task, Object item, String eventType, - String eventName, Object retVal) - { - int level = this.getLevel(task); - this.setLevel(task, --level); - - if (!myLineOpened(task, item)) - { - if (lineOpened()) - System.err.println(); - String spaces = repeat(' ', level); - System.err.print(pidInfo(task) + " " + spaces + eventType + " " + eventName); - } - - System.err.println(" = " + retVal); - - updateOpenLine(null, null); - } - - private void eventSingle(Task task, String eventName) - { - int level = this.getLevel(task); - - if (lineOpened()) - System.err.println("\\"); - System.err.println(pidInfo(task) + " " + repeat(' ', level) + eventName); - - updateOpenLine(null, null); - } hooks/post-receive -- frysk system monitor/debugger