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