This is the mail archive of the
frysk@sources.redhat.com
mailing list for the frysk project.
Remove Code observers on exec
- From: Mark Wielaard <mark at klomp dot org>
- To: frysk at sourceware dot org
- Date: Fri, 29 Sep 2006 18:47:38 +0200
- Subject: Remove Code observers on exec
Hi,
This fixes bug #3255. When we get an execed event the process memory is
overridden and we loose all breakpoints. This patch makes sure we purge
all inserted and pending Code observers and adds a check for this to
TestBreakpoints. I choose to just report deletedFrom() to any pending
observers. The other choice was addFailed() which takes a Throwable as
cause. But when interested in the reason it is better to watch for exec
events.
2006-09-29 Mark Wielaard <mark@klomp.org>
* BreakpointAddresses.java (removeAllCodeObservers): New method.
* Task.java (codeObservers): Make package private.
* TaskState.java (Running.handleExecedEvent): Clean up breakpoints.
* TestBreakpoints.java: Check deletion of Code observers after exec.
2006-09-29 Mark Wielaard <mark@klomp.org>
* funit-breakpoints.c (main): Reexec at the end of the loop.
Committed,
Mark
Index: frysk-core/frysk/pkglibexecdir/funit-breakpoints.c
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/pkglibexecdir/funit-breakpoints.c,v
retrieving revision 1.2
diff -u -r1.2 funit-breakpoints.c
--- frysk-core/frysk/pkglibexecdir/funit-breakpoints.c 23 Aug 2006 04:04:19 -0000 1.2
+++ frysk-core/frysk/pkglibexecdir/funit-breakpoints.c 29 Sep 2006 16:35:33 -0000
@@ -65,8 +65,9 @@
}
int
-main ()
+main (int argc, char *argv[], char *envp[])
{
+
// The number of runs the tester wants us to do.
// Zero when we should terminate.
// Minus one when something went wrong.
@@ -115,5 +116,21 @@
fflush(stdout);
}
- return runs;
+ // Finally re-exec ourselves to show breakpoints are gone.
+ // When called with an argument then we are execing ourselves just to
+ // do a little testrun (all breakpoints should be cleared now).
+ if (argc > 1)
+ return runs;
+ else
+ {
+ char *new_argv[3];
+ new_argv[0] = argv[0];
+ new_argv[1] = "restart";
+ new_argv[2] = NULL;
+ execve (argv[0], new_argv, envp);
+ }
+
+ // Should never be reached.
+ perror ("unreachable");
+ return -1;
}
Index: frysk-core/frysk/proc/BreakpointAddresses.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/BreakpointAddresses.java,v
retrieving revision 1.2
diff -u -r1.2 BreakpointAddresses.java
--- frysk-core/frysk/proc/BreakpointAddresses.java 21 Sep 2006 16:45:01 -0000 1.2
+++ frysk-core/frysk/proc/BreakpointAddresses.java 29 Sep 2006 16:35:33 -0000
@@ -152,4 +152,13 @@
observers = (ArrayList) list.clone();
return observers.iterator();
}
+
+ /**
+ * Called from TaskState when the Task gets an execed event which
+ * clears the whole address space.
+ */
+ void removeAllCodeObservers()
+ {
+ map.clear();
+ }
}
Index: frysk-core/frysk/proc/Task.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/Task.java,v
retrieving revision 1.100
diff -u -r1.100 Task.java
--- frysk-core/frysk/proc/Task.java 21 Sep 2006 16:45:01 -0000 1.100
+++ frysk-core/frysk/proc/Task.java 29 Sep 2006 16:35:33 -0000
@@ -904,7 +904,7 @@
/**
* Set of Code observers.
*/
- private TaskObservable codeObservers = new TaskObservable(this);
+ TaskObservable codeObservers = new TaskObservable(this);
/**
* Add TaskObserver.Code to the TaskObserver pool.
Index: frysk-core/frysk/proc/TaskState.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/TaskState.java,v
retrieving revision 1.116
diff -u -r1.116 TaskState.java
--- frysk-core/frysk/proc/TaskState.java 21 Sep 2006 16:45:01 -0000 1.116
+++ frysk-core/frysk/proc/TaskState.java 29 Sep 2006 16:35:33 -0000
@@ -892,6 +892,18 @@
// Remove all tasks, retaining just this one.
task.proc.retain (task);
((LinuxProc)task.proc).getStat ().refresh();
+
+ // All breakpoints have been erased. We need to explicitly
+ // tell those attached to the current Task.
+ task.proc.breakpoints.removeAllCodeObservers();
+ Iterator it = task.codeObservers.iterator();
+ while (it.hasNext())
+ ((TaskObserver.Code) it.next()).deletedFrom(task);
+
+ it = task.pendingCodeObservers.iterator();
+ while (it.hasNext())
+ ((PendingCodeObserver) it.next()).observer.deletedFrom(task);
+
if (task.notifyExeced () > 0)
{
return (syscalltracing
Index: frysk-core/frysk/proc/TestBreakpoints.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/TestBreakpoints.java,v
retrieving revision 1.5
diff -u -r1.5 TestBreakpoints.java
--- frysk-core/frysk/proc/TestBreakpoints.java 21 Sep 2006 16:45:01 -0000 1.5
+++ frysk-core/frysk/proc/TestBreakpoints.java 29 Sep 2006 16:35:33 -0000
@@ -212,6 +212,27 @@
out.writeByte(0);
out.flush();
+ // The process will now exec itself again.
+ // Make sure Code Observers have been notified.
+ synchronized (monitor)
+ {
+ while (! (code1.isRemoved() && code2.isRemoved()))
+ {
+ try
+ {
+ monitor.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // Ignored
+ }
+ }
+ }
+
+ // And let it go. We are really done.
+ out.writeByte(0);
+ out.flush();
+
// So how did it all go, did it exit properly?
synchronized (monitor)
{
@@ -367,10 +388,35 @@
line = in.readLine();
bp2 = Integer.decode(line).intValue();
+ // For fun (and to test exec) insert another one.
+ CodeObserver code3 = new CodeObserver(breakpoint1);
+ task.requestAddCodeObserver(code3, breakpoint1);
+
// And we are done.
out.writeByte(0);
out.flush();
+ // The process will now exec itself again.
+ // Make sure Code Observers have been notified.
+ synchronized (monitor)
+ {
+ while (! code3.isRemoved())
+ {
+ try
+ {
+ monitor.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // Ignored
+ }
+ }
+ }
+
+ // And let it go. We are really done.
+ out.writeByte(0);
+ out.flush();
+
// Wait for termination. How did it all go, did it exit properly?
synchronized (monitor)
{
@@ -489,6 +535,34 @@
out.writeByte(0);
out.flush();
+ // The process will now exec itself again.
+ // Make sure all the observers are notified that they have been removed.
+ synchronized (monitor)
+ {
+ boolean allRemoved = true;
+ for (int i = 0; i < 1512 && allRemoved; i++)
+ allRemoved = codes1[i].isRemoved() && codes2[i].isRemoved();
+ while (! allRemoved)
+ {
+ try
+ {
+ monitor.wait();
+ }
+ catch (InterruptedException ie)
+ {
+ // ignored
+ }
+
+ allRemoved = true;
+ for (int i = 0; i < 1512 && allRemoved; i++)
+ allRemoved = codes1[i].isRemoved() && codes2[i].isRemoved();
+ }
+ }
+
+ // And let it go. We are really done.
+ out.writeByte(0);
+ out.flush();
+
// Wait for termination. How did it all go, did it exit properly?
synchronized (monitor)
{