* [patch] initial attempt at getting step over signal working
@ 2008-04-12 22:24 Nurdin Premji
0 siblings, 0 replies; only message in thread
From: Nurdin Premji @ 2008-04-12 22:24 UTC (permalink / raw)
To: frysk
[-- Attachment #1: Type: text/plain, Size: 255 bytes --]
Hello everyone,
Attached is some initial work in trying to get stepping over signal
working. It doesn't work yet as there seems to be a big race conditon. (
I managed to run it once and have it succeed, but all subsequent runs fail)
Thank you,
Nurdin
[-- Attachment #2: 0001-Initial-work-on-stepping-over-signal.patch --]
[-- Type: text/x-patch, Size: 18349 bytes --]
From a76ea826a50f9ce025b2935476c72b7e134fef25 Mon Sep 17 00:00:00 2001
From: Nurdin Premji <npremji@localhost.localdomain>
Date: Sat, 12 Apr 2008 16:54:14 -0400
Subject: [PATCH] Initial work on stepping over signal
---
frysk-core/frysk/hpd/StepCommand.java | 12 ++-
frysk-core/frysk/pkglibdir/funit-signal.c | 130 +++++++++++++++++++++
frysk-core/frysk/rt/Breakpoint.java | 5 +-
frysk-core/frysk/stepping/SteppingEngine.java | 83 ++++++++++++--
frysk-core/frysk/stepping/TaskStepEngine.java | 7 +-
frysk-core/frysk/stepping/TestStepping.java | 89 ++++++++++++++
frysk-core/frysk/stepping/TestSteppingEngine.java | 3 +-
7 files changed, 310 insertions(+), 19 deletions(-)
create mode 100644 frysk-core/frysk/pkglibdir/funit-signal.c
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/pkglibdir/funit-signal.c b/frysk-core/frysk/pkglibdir/funit-signal.c
new file mode 100644
index 0000000..e2f11fd
--- /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 <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+
+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)
+{
+
+ if (sig == SIGUSR1) // _signalHandlerEntry_
+ {
+ --j;
+ ++j;
+ }
+ else
+ exit(EXIT_FAILURE);
+
+ return;
+
+}
+
+int
+main (int argc, char ** argv)
+{
+
+ if (argc < 3)
+ {
+ printf("Usage: funit-signal <pid> <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;
+
+}
diff --git a/frysk-core/frysk/rt/Breakpoint.java b/frysk-core/frysk/rt/Breakpoint.java
index 4066f6e..850bbb6 100644
--- a/frysk-core/frysk/rt/Breakpoint.java
+++ b/frysk-core/frysk/rt/Breakpoint.java
@@ -83,7 +83,7 @@ public class Breakpoint implements TaskObserver.Code {
else {
fine.log(this, "updateHit adding instruction observer", task,
"address", address);
- task.requestAddInstructionObserver(this.steppingEngine.getSteppingObserver());
+ this.steppingEngine.requestAddSteppingObserver(task);
this.steppingEngine.addBlocker(task, this);
}
@@ -106,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 7ff86f1..c505407 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);
}
}
@@ -1026,7 +1067,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
@@ -1042,6 +1083,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());
+
// 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
@@ -1104,6 +1153,20 @@ 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() {
@@ -1130,7 +1193,7 @@ public class SteppingEngine {
Iterator i = list.iterator();
while (i.hasNext()) {
t = (Task) i.next();
- t.requestAddInstructionObserver(this.steppingObserver);
+ requestAddSteppingObserver(t);
}
}
@@ -1162,8 +1225,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);
@@ -1302,7 +1365,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;
@@ -1326,7 +1389,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 b14c4f3..059a7c6 100644
--- a/frysk-core/frysk/stepping/TestStepping.java
+++ b/frysk-core/frysk/stepping/TestStepping.java
@@ -135,6 +135,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;
@@ -443,6 +446,91 @@ public class TestStepping extends TestLib {
assertRunUntilStop("Running test");
cleanup();
}
+
+ public void testStepThroughSignal() {
+ /** Variable setup */
+
+ String source = Config.getRootSrcDir()
+ + "frysk-core/frysk/pkglibdir/funit-signal.c";
+
+ this.scanner = new TestfileTokenScanner(new File(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 */
+
+ String source = Config.getRootSrcDir()
+ + "frysk-core/frysk/pkglibdir/funit-signal.c";
+
+ this.scanner = new TestfileTokenScanner(new File(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);
+
+ 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() {
@@ -1151,6 +1239,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 af0da7f..e4e49d3 100644
--- a/frysk-core/frysk/stepping/TestSteppingEngine.java
+++ b/frysk-core/frysk/stepping/TestSteppingEngine.java
@@ -335,8 +335,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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2008-04-12 21:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-12 22:24 [patch] initial attempt at getting step over signal working Nurdin Premji
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).