For documentation purposes, this is what I found to be necessary to really 
clean all window instances. Note that this only works reliably when invoked 
from a non-UI process (e.g. via WAKom).


cleanupWindows
        "in general: the gabage collector seems to be unable to resolve all 
circular dependencies with weak pointers.
        This forces us to explicitly remove the weak pointers to enable garbage 
colltection.
        It also seems to be a problem to invoke the cleanup from within a UI 
process (e.g. from a workspace). 
        Ergo: 
                - when invoked from a workspace not all instances may be 
garbage collected
                - when invoked from a non UI process (e.g. WAKom) all instances 
should have been collected
                - performning a manual garbage collection after having invoked 
this code from a workspace will
                        (usually) remove the pending instances (new process 
context)"
        | count |
        count := 1.
        self
                cleanupEvents;
                cleanupWorkspaces;
                cleanupSystemWindows.
        [ Smalltalk garbageCollect. count := count + 1 ] doWhileFalse: [
                SystemWindow allSubInstances isEmpty or: [ count > 5 "arbitrary 
number" ] ]

cleanupWorkspaces
        PluggableTextMorph allSubInstances do: [ :each | each  
                hasUnacceptedEdits: false;
                askBeforeDiscardingEdits: false;
                myDependents: nil ]

cleanupSystemWindows
        [ [ SystemWindow allSubInstances do: [ :window |
                window 
                        makeClosable;
                        delete ] ] 
                                on: Error 
                                do: [ :ex | 
                                        "may get here because we're trying to 
delete a window which has been deleted already."
                                        ex return  ].
        Smalltalk garbageCollect.
        "already deleted but still hanging aroung (also see #cleanupEvents and 
#cleanupWorkspaces)"
        SystemWindow allSubInstances 
                select: [ :e | e model isNil and: [ e owner isNil ] ]
                thenDo: [ :e |
                        "clean some known places where references can prevent 
GC"
                        UITheme current focusIndicator: nil.
                        ActiveHand mouseOverHandler initialize.
                        ActiveHand keyboardFocus: nil.
                        World cleanseStepList.
                        "e.g. Workspace has a dependents array wich can point 
to the window"
                         (PointerFinder pointersTo: e) do: [ :p | 
                                p class = DependentsArray ifTrue: [
                                        "the first pointer is the 'main' 
pointer in about 99% of the cases"
                                        (PointerFinder pointersTo: p) first 
removeDependent: e ] ] ] 
        ] on: Error do: [ "ignore” ]


On 21.06.2014, at 23:11, Max Leske <[email protected]> wrote:

> Found the problem, documenting it here in case anybody else ever needs this 
> (remember, this is 1.1.1).
> 
> Open a debugger (e.g. by evaluating 1/0), then click into the lower right 
> workspace and type something. OCompletion will now have added an entry to the 
> EventManager actionMap with a ContextVariablesInspector instance as the key. 
> There seems to be a cycle there that can’t be resolved by the garbage 
> collector, since I wasn’t able to find any non weak global pointers (an 
> OContext is referenced by an MessageSend in the action map. The OContext 
> references a morph which is connected to the SystemWindow. Some of those 
> morphs reference the ContextVariablesInspector as their model).
> Anyhow, it should be safe to send EventManager>>cleanUp: with argument true 
> (actionMaps and their contents get recreated on demand), which will release 
> those entries and allow the garbage collector to collect the SystemWindows, 
> other morphs and the Debugger instances.
> 
> Note that this is probably not an issue in later versions (e.g. 3.0 doesn’t 
> include EventManager anymore) but it might be relevant for later 1.x versions.
> 
> Max
> 
> 
> On 21.06.2014, at 20:44, Max Leske <[email protected]> wrote:
> 
>> 
>> On 21.06.2014, at 18:53, Marcus Denker <[email protected]> wrote:
>> 
>>> 
>>> On 21 Jun 2014, at 17:36, kilon alios <[email protected]> wrote:
>>> 
>>>> First off:
>>>> <rant>why do we have an IRC channel if nobody seems to be 
>>>> listening??</rant>
>>>> 
>>>> too small community for an irc channel. My experience with irc is that 
>>>> 90-99% of people logged in at least are idle. For its size #pharo is quite 
>>>> active actually.  
>>>> 
>>> 
>>> I am IRC when at work (and not forgetting to start the IRC client). But 
>>> often when people ask questions it is exactly the wrong moment in time.
>>> I just *can’t*  instantly drop what I am doing an tend to the IRC channel… 
>>> I really wonder how people do it… do they really stop their work right in 
>>> the
>>> miiddle to answer questions? How are they productive? 
>> 
>> I fully agree. I was just momentarily pissed off :)
>> 
>>> 
>>>     Marcus
>>> 
>> 
> 

Reply via email to