From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6821 invoked by alias); 29 Apr 2008 18:25:25 -0000 Received: (qmail 6726 invoked by uid 22791); 29 Apr 2008 18:25:20 -0000 X-Spam-Status: No, hits=0.1 required=5.0 tests=AWL,BAYES_20,J_CHICKENPOX_33,J_CHICKENPOX_45,J_CHICKENPOX_47,J_CHICKENPOX_56,J_CHICKENPOX_65,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 29 Apr 2008 18:24:47 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id m3TIOjws001551 for ; Tue, 29 Apr 2008 14:24:45 -0400 Received: from pobox-3.corp.redhat.com (pobox-3.corp.redhat.com [10.11.255.67]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m3TIOhM3011266 for ; Tue, 29 Apr 2008 14:24:44 -0400 Received: from localhost.localdomain (vpn-14-87.rdu.redhat.com [10.11.14.87]) by pobox-3.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m3TIOgLs005081 for ; Tue, 29 Apr 2008 14:24:42 -0400 Message-ID: <481767EA.6050204@redhat.com> Date: Tue, 29 Apr 2008 23:02:00 -0000 From: Nurdin Premji User-Agent: Thunderbird 2.0.0.12 (X11/20080226) MIME-Version: 1.0 To: frysk Subject: Stepping over signals, in state "detaching" did not handle handleStoppedEvent SIGTRAP(5) Content-Type: multipart/mixed; boundary="------------030400070004020403030202" X-Scanned-By: MIMEDefang 2.58 on 172.16.52.254 X-IsSubscribed: yes Mailing-List: contact frysk-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: frysk-owner@sourceware.org X-SW-Source: 2008-q2/txt/msg00066.txt.bz2 This is a multi-part message in MIME format. --------------030400070004020403030202 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1312 Here is current work on stepping over a signal, the race condition involved is: inside frysk-core: ./TestRunner -debug frysk.stepping.SteppingEngine=FINE frysk.stepping.TestStepping.testStepOverSignal There was 1 error: 1) testStepOverSignal(frysk.stepping.TestStepping)java.lang.RuntimeException: {frysk.proc.live.LinuxPtraceTask@327b6455,pid=29497,tid=29497,state=detaching} in state "detaching" did not handle handleStoppedEvent SIGTRAP(5) at frysk.proc.live.State.unhandled(TestRunner) at frysk.proc.live.LinuxPtraceTaskState$2.handleStoppedEvent(TestRunner) at frysk.proc.live.LinuxPtraceTask.processStoppedEvent(TestRunner) at frysk.proc.live.LinuxWaitBuilder.stopped(TestRunner) at frysk.sys.Wait.wait(TestRunner) at frysk.sys.Wait.wait(TestRunner) at frysk.event.WaitEventLoop.block(TestRunner) at frysk.event.EventLoop.runEventLoop(TestRunner) at frysk.event.EventLoop.runPolling(TestRunner) at frysk.testbed.TestLib.assertRunUntilStop(TestRunner) at frysk.testbed.TestLib.assertRunUntilStop(TestRunner) at frysk.stepping.TestStepping.testStepOverSignal(TestRunner) at frysk.junit.Runner.runCases(TestRunner) at frysk.junit.Runner.runTestCases(TestRunner) at TestRunner.main(TestRunner) happens quite frequently but every once in a while get a pass --------------030400070004020403030202 Content-Type: text/x-patch; name="0001-Stepping-over-signals.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="0001-Stepping-over-signals.patch" Content-length: 16018 >From f41667247d643ca379221e194d49ad65d1bf8527 Mon Sep 17 00:00:00 2001 From: Nurdin Premji Date: Tue, 29 Apr 2008 14:20:57 -0400 Subject: [PATCH] Stepping over signals --- frysk-core/frysk/hpd/StepCommand.java | 12 ++- frysk-core/frysk/rt/Breakpoint.java | 4 +- frysk-core/frysk/stepping/SteppingEngine.java | 87 ++++++++++++++-- frysk-core/frysk/stepping/TaskStepEngine.java | 7 +- frysk-core/frysk/stepping/TestStepping.java | 112 +++++++++++++++++++++ frysk-core/frysk/stepping/TestSteppingEngine.java | 3 +- 6 files changed, 204 insertions(+), 21 deletions(-) diff --git a/frysk-core/frysk/hpd/StepCommand.java b/frysk-core/frysk/hpd/StepCommand.java index a8cc3c0..7cd854e 100644 --- a/frysk-core/frysk/hpd/StepCommand.java +++ b/frysk-core/frysk/hpd/StepCommand.java @@ -60,10 +60,17 @@ public class StepCommand extends ParameterizedCommand { ((Options)options).instruction = true; } }); + + add(new CommandOption("stepoversignal", 's', "step over signals", null) { + void parse(String argument, Object options) { + ((Options) options).stepOverSignal = true; + } + }); } private class Options { boolean instruction = false; + boolean stepOverSignal = false; } Object options() { @@ -79,7 +86,10 @@ public class StepCommand extends ParameterizedCommand { taskList.add(taskIter.next()); } if (cli.steppingObserver != null) { - + if (((Options) options).stepOverSignal == true) { + cli.getSteppingEngine().setStepOverSignal(true); + } + if (((Options) options).instruction == false) { fine.log(this, "Stepping line"); cli.getSteppingEngine().stepLine(taskList); diff --git a/frysk-core/frysk/rt/Breakpoint.java b/frysk-core/frysk/rt/Breakpoint.java index f6214f4..74d0414 100644 --- a/frysk-core/frysk/rt/Breakpoint.java +++ b/frysk-core/frysk/rt/Breakpoint.java @@ -83,7 +83,6 @@ public class Breakpoint implements TaskObserver.Code { else { fine.log(this, "updateHit adding instruction observer", task, "address", address); - this.steppingEngine.blockedByActionPoint(task, this); task.requestUnblock(this); } @@ -107,7 +106,8 @@ public class Breakpoint implements TaskObserver.Code { monitor.notifyAll(); } // System.err.println("BreakPoint.addedTo"); - ((Task) observable).requestDeleteInstructionObserver(this.steppingEngine.getSteppingObserver()); + Task task = (Task) observable; + this.steppingEngine.requestRemoveSteppingObserver(task); } public boolean isAdded () { diff --git a/frysk-core/frysk/stepping/SteppingEngine.java b/frysk-core/frysk/stepping/SteppingEngine.java index c380dd3..13a5ec3 100644 --- a/frysk-core/frysk/stepping/SteppingEngine.java +++ b/frysk-core/frysk/stepping/SteppingEngine.java @@ -53,6 +53,7 @@ import frysk.sys.ProcessIdentifier; import frysk.sys.ProcessIdentifierFactory; import lib.dwfl.DwflLine; import frysk.debuginfo.DebugInfoFrame; +import frysk.debuginfo.DebugInfoStackFactory; import frysk.event.RequestStopEvent; import frysk.proc.Action; import frysk.proc.Manager; @@ -96,6 +97,18 @@ public class SteppingEngine { /* Observer used to block Tasks, as well as providing the mechanism to * step them, by an instruction each time. */ private SteppingObserver steppingObserver; + + public void requestAddSteppingObserver(Task task) + { + task.requestAddInstructionObserver(steppingObserver); + task.requestAddSignaledObserver(steppingObserver); + } + + public void requestRemoveSteppingObserver(Task task) + { + task.requestDeleteInstructionObserver(steppingObserver); + task.requestDeleteSignaledObserver(steppingObserver); + } /* Ensures that newly spawned Tasks are maintained by the SteppingEngine * class, and also makes sure that exiting Tasks are taken care of and cleaned @@ -448,6 +461,26 @@ public class SteppingEngine { this.steppingObserver.notifyNotBlocked(tse); } } + + public void stepOverSignal(Task task) { + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(task); + + long address = frame.getAddress(); + + fine.log(this, "Looking for address: 0x", Long.toHexString(address), "Line #: ", frame.getLine().getLine()); + + TaskStepEngine tse = (TaskStepEngine) this.taskStateMap.get(task); + tse.setState(new StepOutState(task)); + this.steppingObserver.notifyNotBlocked(tse); + + int i = ((Integer) this.contextMap.get(task.getProc())).intValue(); + this.contextMap.put(task.getProc(), new Integer(++i)); + + this.breakpoint = new SteppingBreakpoint(this, address); + this.breakpointMap.put(task, this.breakpoint); + task.requestAddCodeObserver(this.breakpoint, address); + } /** * Performs a step-over operation on a list of tasks; none of the given @@ -479,6 +512,13 @@ public class SteppingEngine { } } } + + + private boolean stepOverSignal = false; + public void setStepOverSignal(boolean bol) { + fine.log(this, "Setting stepOverSignal"); + stepOverSignal = bol; + } /** * Sets the stage for stepping out of a frame. Runs until a breakpoint on the @@ -596,7 +636,7 @@ public class SteppingEngine { this.steppingObserver.notifyNotBlocked(tse); } continueForStepping(t, false); - t.requestDeleteInstructionObserver(this.steppingObserver); + requestRemoveSteppingObserver(t); } } } @@ -715,7 +755,8 @@ public class SteppingEngine { tse = (TaskStepEngine) this.taskStateMap.get(t); tse.setState(new RunningState(t)); this.steppingObserver.notifyNotBlocked(tse); - t.requestDeleteInstructionObserver(this.steppingObserver); + + requestRemoveSteppingObserver(t); } return; } else @@ -735,7 +776,7 @@ public class SteppingEngine { tse = (TaskStepEngine) this.taskStateMap.get(t); tse.setState(new RunningState(t)); this.steppingObserver.notifyNotBlocked(tse); - t.requestDeleteInstructionObserver(this.steppingObserver); + requestRemoveSteppingObserver(t); } else { /* Put all threads back into a master list */ temp.add(t); @@ -829,7 +870,7 @@ public class SteppingEngine { t.requestDeleteTerminatingObserver(this.threadLifeObservable); t.requestDeleteTerminatedObserver(this.threadLifeObservable); t.requestDeleteClonedObserver(this.threadLifeObservable); - t.requestDeleteInstructionObserver(this.steppingObserver); + requestRemoveSteppingObserver(t); cleanTask(t); } } @@ -895,7 +936,8 @@ public class SteppingEngine { public SteppingObserver getSteppingObserver() { return this.steppingObserver; } - + + /** * Sets a SteppingBreakpoint on the given Task at the given address. * @@ -990,7 +1032,7 @@ public class SteppingEngine { // Requests the addition of the stepping observer to task if // not inserted already. if (!(task.isInstructionObserverAdded(this.steppingObserver))) { - task.requestAddInstructionObserver(this.steppingObserver); + requestAddSteppingObserver(task); } // Add the observer to the task's blockers list @@ -1053,7 +1095,7 @@ public class SteppingEngine { } protected class SteppingObserver extends Observable implements - TaskObserver.Instruction { + TaskObserver.Instruction, TaskObserver.Signaled{ /** * Callback for TaskObserver.Instruction. Each time a Task is blocked, either @@ -1069,6 +1111,14 @@ public class SteppingEngine { * @return Action.BLOCK Continue blocking this incoming Task */ public synchronized Action updateExecuted(Task task) { + + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(task); + + long address = frame.getAddress(); + + fine.log(this, "At address: 0x", Long.toHexString(address), "Line #: ", frame.getLine().getLine(), "stepOverSignal set to: " + stepOverSignal); + // System.err.println("SE.SO.updateEx: " + task); /* Check to see if acting upon this event produces a stopped state * change. If so, decrement the number of Tasks active in the Task's @@ -1131,6 +1181,19 @@ public class SteppingEngine { this.setChanged(); this.notifyObservers(tse); } + + public Action updateSignaled(Task task, Signal signal) { + fine.log(this, "updateSignaled called"); + if (stepOverSignal) { + fine.log(this, "updateSignaled, stepping over"); + + requestRemoveSteppingObserver(task); + stepOverSignal(task); + fine.log(this, "finished step over signal"); + return Action.BLOCK; + } + return Action.CONTINUE; + } } public void requestAdd() { @@ -1157,7 +1220,7 @@ public class SteppingEngine { Iterator i = list.iterator(); while (i.hasNext()) { t = (Task) i.next(); - t.requestAddInstructionObserver(this.steppingObserver); + requestAddSteppingObserver(t); } } @@ -1189,8 +1252,8 @@ public class SteppingEngine { offspring, SteppingEngine.this)); SteppingEngine.this.threadsList.addLast(offspring); - offspring.requestAddInstructionObserver(SteppingEngine.this.steppingObserver); - + requestAddSteppingObserver(offspring); + offspring.requestAddClonedObserver(this); offspring.requestAddTerminatingObserver(this); offspring.requestAddTerminatedObserver(this); @@ -1329,7 +1392,7 @@ public class SteppingEngine { addy = address; fine.log(this, "updateHit task", task, "address", address, "adding instruction observer"); - task.requestAddInstructionObserver(SteppingEngine.this.steppingObserver); + requestAddSteppingObserver(task); } ++triggered; @@ -1353,7 +1416,7 @@ public class SteppingEngine { } Task t = (Task) observable; - t.requestDeleteInstructionObserver(steppingObserver); + requestRemoveSteppingObserver(t); continueForStepping(t, false); } diff --git a/frysk-core/frysk/stepping/TaskStepEngine.java b/frysk-core/frysk/stepping/TaskStepEngine.java index be1cf4b..9120fd5 100644 --- a/frysk-core/frysk/stepping/TaskStepEngine.java +++ b/frysk-core/frysk/stepping/TaskStepEngine.java @@ -183,17 +183,16 @@ public class TaskStepEngine { } /** - * Returns the current State of this TaskStepEngine's Task. + * Sets the current State of this TaskStepEngine's Task. * - * @param newState - * The current State of this TaskStepEngine's Task + * @param newState The new State of this TaskStepEngine's Task */ public void setState(State newState) { this.state = newState; } /** - * Sets the current State of this TaskStepEngine's Task. + * Returns the current State of this TaskStepEngine's Task. * * @return state The current State of this TaskStepEngine's Task. */ diff --git a/frysk-core/frysk/stepping/TestStepping.java b/frysk-core/frysk/stepping/TestStepping.java index 188a27f..ca069e8 100644 --- a/frysk-core/frysk/stepping/TestStepping.java +++ b/frysk-core/frysk/stepping/TestStepping.java @@ -49,9 +49,11 @@ import frysk.testbed.SynchronizedOffspring; import frysk.config.Prefix; import frysk.debuginfo.DebugInfoFrame; import frysk.debuginfo.DebugInfoStackFactory; +import frysk.proc.Action; import frysk.proc.Manager; import frysk.proc.Proc; import frysk.proc.Task; +import frysk.proc.TaskObserver.Terminated; import frysk.rt.BreakpointManager; import frysk.rt.LineBreakpoint; import frysk.rt.SourceBreakpoint; @@ -134,6 +136,9 @@ public class TestStepping extends TestLib { assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); /** The stepping operation */ + + //Send a signal to myTask + this.se.stepLine(theTask); this.testStarted = true; @@ -431,6 +436,112 @@ public class TestStepping extends TestLib { assertRunUntilStop("Running test"); cleanup(); } + + public void testStepThroughSignal() { + /** Variable setup */ + + File source = Prefix.sourceFile("frysk-core/frysk/pkglibdir/funit-signal.c"); + + this.scanner = new TestfileTokenScanner(source); + + /* The line number where the test begins */ + int start = this.scanner.findTokenLine("_signalRaiseCall_"); + + /* The line number the test should end up at */ + int end = this.scanner.findTokenLine("_signalHandlerEntry_"); + + /* The test process */ + SynchronizedOffspring process + = new SynchronizedOffspring(Signal.USR1, + new String[] { + getExecPath("funit-signal"), + Integer.toString(Pid.get().intValue()), + Integer.toString(Signal.USR1.intValue()) + }); + this.testStarted = false; + + /** Test initialization */ + Task myTask = initTask(process, source, start, end); + + this.currentTest = new AssertLine(end, myTask); + + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(myTask); + assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); + + /** The stepping operation */ + this.se.stepLine(myTask); + + this.testStarted = true; + + /** Run to completion */ + assertRunUntilStop("Running test"); + cleanup(); + } + + public void testStepOverSignal() { + /** Variable setup */ + + File source = Prefix.sourceFile("frysk-core/frysk/pkglibdir/funit-signal.c"); + + this.scanner = new TestfileTokenScanner(source); + + /* The line number where the test begins */ + int start = this.scanner.findTokenLine("_signalRaiseCall_"); + + /* The test process */ + SynchronizedOffspring process + = new SynchronizedOffspring(Signal.USR1, + new String[] { + getExecPath("funit-signal"), + Integer.toString(Pid.get().intValue()), + Integer.toString(Signal.USR1.intValue()) + }); + this.testStarted = false; + + /** Test initialization */ + Task myTask = initTask(process, source, start, start); + + myTask.requestAddTerminatedObserver(new Terminated(){ + + public Action updateTerminated(Task task, + frysk.isa.signals.Signal signal, int value) { + // TODO Auto-generated method stub + return null; + } + + public void addFailed(Object observable, Throwable w) { + // TODO Auto-generated method stub + + } + + public void addedTo(Object observable) { + // TODO Auto-generated method stub + + } + + public void deletedFrom(Object observable) { + // TODO Auto-generated method stub + + }}); + + this.se.setStepOverSignal(true); + + this.currentTest = new AssertLine(start, myTask); + + DebugInfoFrame frame = DebugInfoStackFactory + .createDebugInfoStackTrace(myTask); + assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); + + /** The stepping operation */ + this.se.stepLine(myTask); + + this.testStarted = true; + + /** Run to completion */ + assertRunUntilStop("Running test"); + cleanup(); + } public void testASMSingleStep() { @@ -1125,6 +1236,7 @@ public class TestStepping extends TestLib { DebugInfoFrame frame = DebugInfoStackFactory .createDebugInfoStackTrace(task); int lineNr = frame.getLine().getLine(); + assertEquals("line number", success, lineNr); Manager.eventLoop.requestStop(); } diff --git a/frysk-core/frysk/stepping/TestSteppingEngine.java b/frysk-core/frysk/stepping/TestSteppingEngine.java index bbe5ad1..62ce036 100644 --- a/frysk-core/frysk/stepping/TestSteppingEngine.java +++ b/frysk-core/frysk/stepping/TestSteppingEngine.java @@ -330,8 +330,7 @@ public class TestSteppingEngine extends TestLib { assertTrue("Line information present", frame.getLine() != SourceLocation.UNKNOWN); /** The stepping operation */ - this.se.stepOver(theTask, DebugInfoStackFactory - .createDebugInfoStackTrace(theTask)); + this.se.stepOver(theTask, frame); this.testStarted = true; // System.err.println("waiting for finish"); -- 1.5.4.1 --------------030400070004020403030202 Content-Type: text/x-patch; name="0002-Added-funit-signal.c.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="0002-Added-funit-signal.c.patch" Content-length: 4076 >From 560975fbd0c8f181342d71829a98d86dda4380bc Mon Sep 17 00:00:00 2001 From: Nurdin Premji Date: Tue, 29 Apr 2008 14:23:16 -0400 Subject: [PATCH] Added funit-signal.c --- frysk-core/frysk/pkglibdir/funit-signal.c | 130 +++++++++++++++++++++++++++++ 1 files changed, 130 insertions(+), 0 deletions(-) create mode 100644 frysk-core/frysk/pkglibdir/funit-signal.c diff --git a/frysk-core/frysk/pkglibdir/funit-signal.c b/frysk-core/frysk/pkglibdir/funit-signal.c new file mode 100644 index 0000000..f227d3d --- /dev/null +++ b/frysk-core/frysk/pkglibdir/funit-signal.c @@ -0,0 +1,130 @@ +// This file is part of the program FRYSK. +// +// Copyright 2008, 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 volatile interfaces identified in the file named EXCEPTION found in +// the source code files (the "Approved volatile interfaces"). The files of +// Non-GPL Code may instantiate templates or use macros or inline +// functions from the Approved volatile 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 volatile 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. + +#include +#include +#include +#include +#include +#include + +pthread_t tester_thread; + + +volatile int j = 0; +volatile int lock = 1; +volatile int sig; +volatile pid_t pid; + +void +*signal_parent () +{ + while (lock); + + kill (pid, sig); + + while(1); +} + +void +handler (int sig) +{ // _signalHandlerEntry_ + + if (sig == SIGUSR1) + { + --j; + ++j; + } + else + exit(EXIT_FAILURE); + + return; + +} + +int +main (int argc, char ** argv) +{ + + if (argc < 3) + { + printf("Usage: funit-signal \n"); + exit(0); + } + + errno = 0; + pid_t target_pid = (pid_t) strtoul(argv[1], (char **) NULL, 10); + if (errno) + { + perror ("Invalid pid"); + exit (EXIT_FAILURE); + } + + errno = 0; + int signal = (int) strtoul (argv[2], (char **) NULL, 10); + if (errno) + { + perror ("Invalid signal"); + exit (EXIT_FAILURE); + } + + pid = target_pid; + sig = signal; + + struct sigaction sa; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGUSR1, &sa, NULL); + + pthread_create (&tester_thread, NULL, signal_parent, NULL); + + lock = 0; + + while(1) + { + --j; + ++j; + --j; + ++j; + raise(SIGUSR1); // _signalRaiseCall_ + } + return 0; + +} -- 1.5.4.1 --------------030400070004020403030202--