Bug 4889

Summary: adding new codeObserver in updateHit causes java.lang.IllegalStateException: Already stepping
Product: frysk Reporter: Petr Machata <pmachata>
Component: generalAssignee: Unassigned <frysk-bugzilla>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: unspecified   
Target Milestone: ---   
Host: i686-pc-linux-gnu Target:
Build: Last reconfirmed:
Bug Depends on:    
Bug Blocks: 2229    

Description Petr Machata 2007-08-03 12:26:27 UTC
FC6.

Adding new codeObserver in updateHit causes java.lang.IllegalStateException:
Already stepping.  The stack trace I'm getting:
Exception in thread "main" java.lang.IllegalStateException: Already stepping
   at frysk.proc.Breakpoint.prepareStep(fltrace)
   at frysk.proc.live.LinuxTaskState$Running.sendContinue(fltrace)
   at frysk.proc.live.LinuxTaskState$Running.handleStoppedEvent(fltrace)
   at frysk.proc.live.LinuxTask.processStoppedEvent(fltrace)
   at frysk.proc.live.LinuxWaitBuilder.stopped(fltrace)
   at frysk.sys.Wait.wait(fltrace)
   at frysk.sys.Wait.waitAll(fltrace)
   at frysk.event.WaitEventLoop.block(fltrace)
   at frysk.event.EventLoop.runEventLoop(fltrace)
   at frysk.event.EventLoop.run(fltrace)
   at frysk.util.Ltrace.trace(fltrace)
   at frysk.bindir.fltrace.run(fltrace)
   at frysk.bindir.fltrace.main(fltrace)

This doesn't seem to happen when requesting observation of already observed
state.  The problem also goes away when I do

      task.requestUnblock(this);
      return Action.BLOCK;

intead of return Action.CONTINUE.  The problem also went away when something
like that was in effect:

      task.getProc().getMainTask().requestAddCodeObserver(this, retAddr);
      System.err.println("[" + task.getTaskId().intValue() + "]");

All this seems to point to the problem of frysk having "enough time" to do the
observer shenanigans, as is suggested by comments on several places.

`retAddr' given above could have been arbitrary, e.g. I tried to enter
0x080483b4, the address of main in my testing binary, so the problems wasn't in
that I'd request breakpoint inside data segment or something.
Comment 1 Mark Wielaard 2007-08-03 12:57:44 UTC
This is related/similar to bug #4747 with the difference that frysk itself is
responsible for generating the stop signal to install the breakpoint instead of
an external trigger.

This will be fixed with the fix for #4747. The "workaround":

      task.requestAddCodeObserver(observer, address);
      task.requestUnblock(this);
      return Action.BLOCK;

Is most likely what you actually want. It makes sure that the observer is
installed and only after that the task is unblocked. If you use the sequence:

      task.requestAddCodeObserver(observer, address);
      return Action.CONTINUE;

The request to add the new observer is only pending and the task might already
be running long before the observer is installed (so you could miss hitting that
breakpoint). This is actually what is happening here.
Comment 2 Mark Wielaard 2007-08-10 11:23:35 UTC
New testcase added: frysk.proc.TestTaskObserverCode.testInstallCodeDuringCode
Comment 3 Mark Wielaard 2007-08-15 11:08:07 UTC
Fixed by:

frysk-core/frysk/proc/ChangeLog
2007-08-15  Mark Wielaard  <mwielaard@redhat.com>
 
    * getSetupAddress (getSetupAddress): New method.
    (stepAbort): Likewise.
    * TestTaskObserverCode.java (testCodeSignalInterrupt): Enable test.
    (testInstallCodeDuringCode): Likewise.
    (Symbol): New static helper class.
    (getGlobalLabelAddress): New helper method.
    (breakTest): New test harness for funit-raise.
    (testBreakDivZero): New test based on breakTest.
    (testBreakIllegalAddress): Likewise.
    (testBreakIllegalInstruction): Likewise.
    (testBreakSignalTerminate): Likewise.
    (testBreakSignalIgnore): Likewise.
    (AttachedObserver.task): New field.
    (updateAttached): Set task field.
    (TerminatingObserver.task): New field.
    (TerminatingObserver.signal): Likewise.
    (TerminatingObserver.value): Likewise.
    (TerminatingObserver.updateTerminating): Set new fields.

frysk-core/frysk/proc/live/ChangeLog
2007-08-15  Mark Wielaard  <mwielaard@redhat.com>

    * LinuxTaskState.java (Stepping.handleTrappedpEvent): Always check
    steppingBreakpoint.
    (checkBreakpointStepping): New helper method.
    (handleSignaledEvent): Use checkBreakpointStepping before
    continuing.
    (handleStoppedEvent): Likewise.

frysk-core/frysk/pkglibdir/ChangeLog
2007-08-15  Mark Wielaard  <mwielaard@redhat.com>

    * funit-raise.S: New test.