Debugger woes

Andreas Raab andreas.raab at gmx.de
Tue Sep 2 12:01:53 UTC 2003


Hi Anthony,

> I wanted to execute the unwind blocks in the context of the 
> terminating process and not the calling process.  Meaning if
> an unwind block raises an exception, an exception handler in
> the terminating process will handle it and not one in the
> calling process.

Ah, I see. Is this the "standard" semantics? 
E.g., what do other systems do when you have something like

p := [[
	 [Processor activeProcess suspend] ensure:[4/0]
	] on: ZeroDivide do:[:ex| ex resume: 'oh no'].
     ] fork.
p terminate.

> It sounds like you want to keep a copy of the process (a 
> continuation), so you can abort what you did in the debugger.

I didn't think about it this way, but yes, I guess that's what I'm after.
The reason being that for debugging something like Croquet processes I
_think_ we'll have to a little more than "just" simulating the process
itself - turns out that the environmental factors (such as the real-time
clock) plays an important role which we can't really ignore when we debug
such processes.

> > One of the changes that I've thought about for the purpose 
> > of debugging processes was to essentially associate a debugger
> > with a process (via instVar) which - if present - handles
> > attempts to do things with the process where potentially 
> > "incorrect" state (such as suspendedContext) is involved.
> > The places which come to mind immediately are (for example) 
> > #suspend, #resume, and #terminate but there may be others.
> > In the context of a debug session, we may indeed forward
> > these requests to the debugger which could
> > then provide us with the "right" means for handling them.
> 
> Are you talking about locking the process while mainpulating it, so it
> is not inadvertently resumed before you are done manipulating it?

Yes, exactly. The point being that the "locked" process really has a few
more constraints when we debug it. I'll give a simple example from Croquet:
Each process has an associated deadline by which to deliver it's associated
"payload". When this deadline expires the process will be terminated as it
has been unable to deliver its payload in a timely fashion. Now, typically
the deadline is tightly bound to real-time and you can imagine what kind of
"interesting" behavior you get if the deadline kicks in while you try to
debug this process ;-) So one of the things I'd like to do is to arbitrarily
expand the deadline for the purpose of a debug session. Note that while this
_sounds_ simple (just change the deadline) it actually isn't. The "realtime
deadline" needs to abort just the way it would in normal execution but the
process needs to be debugged "as if" the realtime hasn't been reached. Kinda
tricky, and I'd like to have this model represented explicitly somewhere
(e.g., in the simulator/debugger).

> I still don't see the difference between running and simulating.  You
> are going through the same execution steps, its just one is written in
> Smalltalk and the other is written in Slang.

If you exclude environmental factors, yes. But see above - I don't really
see how you could debug a process with croquet semantics without
distinguishing between "real" and "simulated" execution (btw, perhaps as a
final note for the above - if we resume a debugged Croquet process _before_
its deadline expires we should naturally be able to complete it "in time" ;)

> > where exactly does this happen? I have done some pretty weird things
> > with contexts myself but _that_ method is really beyound me ;-)
> 
> Yes, sorry context swapping (#jump) is a little perverse plus 
> it wasn't
> commented well enough.  Attached is a new version that does normal
> process resuming instead of context swapping and is better commented.

Thanks, I'll check it out.

> The version attached addresses the changes I was referring to except
> for adding a don't-quickStep preference which you said you don't want.

Yup, that's fine. One more question because I'm sure you must have thought
about it: Do you have any idea about an idiom that can be used for
retrieving the active process in the context of a debug session? Most of
what's happening could be solved by "somehow" making sure that a simulated
"Processor activeProcess" answers the process being debugged instead of the
one debugging it. For example, I have thought about something where a
process which runs for some reason another one (such as in process unwind)
might remember the process being simulated and answer this process. For
example,

Processor>>activeProcess
	^activeProcess runningProcess

Process>>runningProcess
	"Answer the process we are currently running. If the receiver is for
some reason simulating the execution of another process, the simulated
process will be stored in the simulatedProcess instance variable."
	^simulatedProcess ifNil:[self]

would give us the basics. However, this still won't be complete as then it
is questionable how the simulation of "Processor activeProcess suspend"
should work. This is why I'd like to have a lightweight debugger/simulator
associated with the process which captures requests like those. For example

Process>>runningProcess
	^debugger ifNil:[self] ifNotNil:[debugger runningProcess]

Process>>suspend
	debugger ifNotNil:[
		debugger runningProcess == self ifTrue:[debugger
suspendProcess: self].
	].

Debugger>>suspendProcess: aProcess
	"Simulate suspension of the currently running process"
	SuspendDebuggerProcess signal. "will be caught by the simulation
somewhere up"

etc. Of course, the _really_ interesting question here is what's going to
happen in a case like
	[ ["..."] ensure:[Processor activeProcess suspend]] 
		ensure:[Transcript show: 'been here, done that']]

but that's too obscure to even think about it ;-)

Cheers,
  - Andreas



More information about the Squeak-dev mailing list