[comp.windows.ms.programmer] Re^2: Actor specific questions

kend@data.UUCP (Ken Dickey) (03/22/91)

adw@otter.hpl.hp.com (Dave Wells) writes:

>This seems to allow you to get into the debugger reliably. If you keep
>hitting "OK" on the debug dialog, however, ACTOR siezes up after a few more
>repaints - cause unknown.

In all cases of this type I have seen, code is (recursively) grabbing new
instances of the Windows drawing context and not giving it up.  As there
are a limited number of these (Windows resource limit), Windows dies.

-Ken Dickey					kend@data.uucp

adw@otter.hpl.hp.com (Dave Wells) (04/03/91)

From: pcb@basin04.cacs.usl.edu (Peter C. Bahrs)

;And finally, for now, has anyone figured out how to modify the interpreter
;so that when an application does something stupid and the debugger
;comes up, the application will not try to process any more messages?

I wrote:

Not in general. The paint() -> debugger -> paint() -> debugger...
loop can be solved:

[details omitted]

kend@data.UUCP  Ken Dickey at Microcosm, Beaverton, OR

|adw@otter.hpl.hp.com (Dave Wells) writes:

|>This seems to allow you to get into the debugger reliably. If you keep
|>hitting "OK" on the debug dialog, however, ACTOR siezes up after a few more
|>repaints - cause unknown.

|In all cases of this type I have seen, code is (recursively) grabbing new
|instances of the Windows drawing context and not giving it up.  As there
|are a limited number of these (Windows resource limit), Windows dies.

You're quite right - thanks for pointing this out. Window:WM_PAINT()
provides the BeginPaint/EndPaint pair required by Windows. If paint()
traps to the debugger, closing the debug window abandons the WM_PAINT
message loop, and EndPaint never gets called. What I've done is:

    o Add an instance variable "hDc" to my application's WindowClass
        descendant.

    o Override WM_PAINT() thus:

        hDc := Call BeginPaint(hWnd, paintStruct);
        /* (hDc flags "doing a WM_PAINT") */
        paint(self, hDc);
        cleanupPaint(self);
        hDc := nil;
        ^0;

    o Add a cleanupPaint method thus:

        if hDc then Call EndPaint(hWnd, paintStruct); endif;

    o Add lines to the start of SystemClass:abort() thus:

        if findFunction(class(ThePort:late),#cleanupPaint)
        then /* Now absolutely sure there's a method to call - we don't
                want a trap from here! */
          cleanupPaint(ThePort:late);
        endif;

I'd be interested in any substantially simpler fix.

I've also improved the debugger "recursion" trap within paint():

Def paint(self, hdc | frames, myName, calledFromDebugger)
Redraws self. */
{ /* First, guard against the dreaded "debug recursion": */
  if (frames := frames(Bug))
  then
    myName := asString(findFunction(class(self),#paint));
    do (frames,{using(frame)
      if subString(frame,0,size(myName)) = myName
      then calledFromDebugger := true;
      endif;
    });
  endif;
  /* NOTE that although this will prevent infinite debugger invocations,
     the paint structure and display context must still be deallocated.
     Modify SystemClass:abort() to call self:cleanupPaint() to achieve
     this. */
  if calledFromDebugger
  then
    printLine(myName+"() called, but debugger is up.");
  else
    draw(self);
  endif;
}!!

This allows repaints if the debugger has been invoked by the execution of a
message other than WM_PAINT.

Dave Wells