Process local variable and debugging

Stephen Pair spair at advantive.com
Wed Feb 13 04:24:43 UTC 2002


> The first problem comes down to 'context' or 'Process'; are 
> these process global variables to be considered to belong to 
> the stack of contexts currently above the active context, or 
> are they to belong to the Process? Which Process - how do you 
> work out which process is attached to the context?

I think they belong with the Process, though that doesn't mean that you
wouldn't access the process via the context.  Most of the uses of
process globals (or thread local storage as other systems refer to it)
that I've seen fit most naturally with the Process.  Here are a couple
of examples that I can think of:

	"What network request is this process attempting to satisfy?"
	"What capabilities should this process be allowed to invoke?"
	"What user does this process belong to?"

> If to the context stack, then we are reasonably safe in 
> scanning up the stack and finding a place where we can 
> consider it to be the root. Or we could (ab)use the exception 
> handlers and allow overriding of these values anywhere in the 
> stack. 

I actually implemented something like this in the Comanche Process
extension (the one that adds 'context' to Process).  I allowed not only
for this to be a dictionary of named process globals, I also allowed you
to stack several dictionaries up to override a given value at any
position in the stack (allowing it to be restored).  As it turns out,
this was overkill and mostly unnecessary for a couple of reasons.
First, I have yet to find a compelling use of it, and second, you can
just set the value of a process global to something, make a call, then
restore the old value (protecting this with ensure).  For example:

	oldUser := thisContext process user.
	thisContext process user: someNewUser.
	[self doSomething] ensure: [thisContext process user: oldUser].

> Or we could have a simpified prim similar to the 
> exception handler prim that just finds the root context. 
> Things remain safe almost no matter what we do with 
> #swapSenders: and other fun stack manipulations, though the 
> effects might be amusing. The drawback is that scanning the 
> stack is somwhat slower than merely accessing variables. It 
> should be safe in the debugger though, both practically and 
> semantically.

I think Anthony's solution using "thisContext process" is best way to
work around this debugger issue...it's relatively fast in the
non-debugger case, and would work with the debugger (provided you
implement something like what you describe above)...however, I still
contend that the debugger is at fault for butting into another
processes' business without setting things up properly.  What other
cases besides the debugger is this is an issue?

As for the findProcess algorithm, I'd say that performance is not so
much an issue since you only need it when "self ~= thisContext sender"
(in the #process method of the context).  That should only happen in
special cases (like debugging) correct?  As for the actual
implementations, I don't have much to offer at this point...to me, it
seems like fixing the debugger would be easier.  Why not have a method
like Process>>cloneForDebugging or Process>>newForDebugging (the child
process would inherit all of the context of its parent, including the
process globals).

> For the process, we have only Processor activeProcess as a 
> mechanism for now. At least, I don't know any good way to 
> reliably get the process from a context (barring Anthony's 
> changes). When debugging, we could possibly trap 
> #activeProcess (it looks easiest to me if we give it a fake 
> primitive, then it can be picked up in ContextPart>
> doPrimitive:method:receiver:args:) to return the process 
> being debugged. What happens if you do a doit in the debugger 
> and really want the actual active process though?

How hard is it to change the debugger to use a dedicated process for
debugging where the process state (i.e. its globals) is copied from the
original process (the debugger itself would run in a separate process)?
Such a process could be used for doIts as well.

> The second idea was that described by Dave Simmons; swap the 
> values of the Associations in the literal frames of the 
> affected methods. This gets past the problem of the wrong 
> activeProcess, but does involve potential messing around when 
> debugging - the process running the debugger mustn't change 
> the values that were/are in use by the debuggee. I'm also 
> still unsure of exactly what one needs to do to implement 
> this idea for anything but the most trivial case; since we 
> would have to set the values of any/all Association involved 
> for every process suspend/resume it seems like it could get 
> expensive for more than a couple. Maybe the answer is to only 
> have one, and have it be a dictionary of the rest of the 
> variables of interest?

I think these are good ideas if it's desirable to use process globals in
a similar way that regular globals are used.  Otherwise, you can just
invoke methods on the process to get at what you need.

- Stephen




More information about the Squeak-dev mailing list