This is the mail archive of the frysk@sources.redhat.com mailing list for the frysk project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)
       {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]