[squeak-dev] Debugging of other processes with wait

Eliot Miranda eliot.miranda at gmail.com
Thu Jul 23 14:37:03 UTC 2020


Hi Jakob,

    first, this seems like a really important issue that if addressed would improve the debugger a lot.  So in my asking questions I’m not trying to knock dune your proposals, only trying to understand the problem accurately.

> On Jul 23, 2020, at 5:50 AM, Jakob Reschke <forums.jakob at resfarm.de> wrote:
> 
> Hello,
> 
> Yesterday I needed to debug a process that is not the UI process. At
> one point this background process waits on a Promise (so it will wait
> on a Semaphore) that is supposed to be resolved in the UI process, so
> the background process will block. If this point is reached while
> stepping in the debugger, the UI process will block instead, since it
> evaluates the debugger stepping on behalf of the background process.

Can you describe the control flow when this occurs normally, outside the debugger?  I need to understand which processes execute waits.

> What I did for now is to add an accessor on ProcessScheduler that
> answers the activeProcess without sending #effectiveProcess, and check
> in Promise>>wait whether this real active process is the UI process.
> If it is, halt the debugged process before the Semaphore wait
> primitive, and I proceed manually as soon as I am confident that the
> promise is already resolved or rejected, so the wait will return
> immediately.

An alternative might be to have the debugger spawn a new UI process whenever it detects that the UI process is blocked.  This may have to be done by a background helper process that the debugger spawns or allows to run whenever the debugger steps, because of course the ui process is executing the step.

Without thinking things through, another alternative might be to have the debugger always use its own process.  The underlying issue is that if the ui process blocks in reality then it should block in the debugger, but we’d like to keep the debugger alive and we’d like to keep the ui alive.

So I suppose we could introduce a background process whose job it is to observe the ui process and if it detects the ui process is blocked for some time (1 second?) spawns a new ui process had reports (in the Transcript?, a pop-up in the new ui process?) that the ui process blocked.

> 
> wait
>    "Wait unconditionally for this promise to become fulfilled or rejected."
>    | sema |
>    (state = #pending and: [Processor realProcess == Project
> uiProcess]) ifTrue: [self halt].
>    sema := Semaphore new.
>    ...
> 
> But of course this is just a workaround. Is there a chance to extend
> the Squeak debugger to deal with critical sections and waits?

I don’t see how.  The debugger can spot a critical section entry or a wait if one is doing “send”, because then the debugger actually executes the primitive in Context>>#tryPrimitive:..., (IIRC, I’m on my phone).  But if the debugger steps then the critical section entry or wait will be executed by running code (the debugger runs step at full speed by using perform: and the code executed by the perform, while surrounded by an exception handler and an unwind-protect, is not virtualised in any way and so we have no easy way of intercepting critical section entry or waits).

> In
> Eclipse for example, there is a list of threads; blocked/waiting
> threads are annotated with an icon, as well as the top frame that
> waits for something; you can debug other threads in the meantime. But
> in Java the debugger is in another VM than the debugged process, so
> the situation that the debugger steps in the UI process needs not be
> resolved there in the first place.
> 
> Maybe if we know all the points/primitives where processes can be
> blocked, we could make the stepping detect these, run them in another
> process, make the debugger observe that process and show some info
> about the waiting in a special top context in the meantime. Once the
> other process is unblocked (or terminated if it does nothing else than
> the wait), the debugger would continue to step the background process.
> Could this work?
> 
> Or is there already another facility that works and which I should use?

As I say, I think a way that can work is detecting that the ui process has blocked and spawning a new ui process when that happens.  But when in the debugger we want to avoid the debugger blocking in step/send and hence only executing any actions before step/send and not those after step/send (eg removing exception handler and unwind-protect from the stack).  So architecturally, not having the debugger use the ui process and to use its own process seems like a good idea but a major change.

> Kind regards,
> Jakob

Cheers,
Eliot


More information about the Squeak-dev mailing list