OOP leaking with registered object

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

OOP leaking with registered object

Roland Plüss-2
I'm trying to figure out why I've got a leak with GST. It's about a C++
program hosting smalltalk as script language. Let's say you've got this
scenario:

class Something:
   OOP app
   Init():
      gst_initialize( NULL, NULL, GST_NO_TTY )
      // add classes and stuff
      app = gst_perform( classApp, selectorNew ) // calls also init
      gst_register_oop( app );
   CleanUp():
      app = gst_perform( classApp, selectorCleanup ) // calls cleanup
      gst_unregister_oop( app );
      // clean up classes and stugg
      gst_invoke_hook( GST_ABOUT_TO_QUIT )

Furthermore let's say a smalltalk script does something simple like this:
MyApp subclass: App [
   | x |
   init [ x := CEnabledClass new ]
   cleanup [ x := nil ]

No other object stores a reference to x for this simple test. Now x is
always leaking. Furthermore OOP app is leaking (if I set it to call
finalize and printf on finalize[] nothing happens).

I can verify that if X is created somewhere in smalltalk function and
going out of scope it is properly destroyed if not used and does not leak.

If assigned to OOP app x leaks because OOP app is not freed. Most
probably OOP app is simply not garbage collected in that short time?

Is there a way to force garbage collection before shutting down?

--
Yours sincerely
Plüss Roland

Leader and Head Programmer
- Game: Epsylon ( http://www.indiedb.com/games/epsylon )
- Game Engine: Drag[en]gine ( http://www.indiedb.com/engines/dragengine
, http://dragengine.rptd.ch/wiki )
- Normal Map Generator: DENormGen ( http://epsylon.rptd.ch/denormgen.php )
- As well as various Blender export scripts und game tools


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Paolo Bonzini-2


On 03/04/2015 21:30, Roland Plüss wrote:

> I'm trying to figure out why I've got a leak with GST. It's about a
> C++ program hosting smalltalk as script language. Let's say you've
> got this scenario:
>
> class Something: OOP app Init(): gst_initialize( NULL, NULL,
> GST_NO_TTY ) // add classes and stuff app = gst_perform( classApp,
> selectorNew ) // calls also init gst_register_oop( app );
> CleanUp(): app = gst_perform( classApp, selectorCleanup ) // calls
> cleanup gst_unregister_oop( app ); // clean up classes and stugg
> gst_invoke_hook( GST_ABOUT_TO_QUIT )
>
> Furthermore let's say a smalltalk script does something simple like
> this: MyApp subclass: App [ | x | init [ x := CEnabledClass new ]
> cleanup [ x := nil ]
>
> No other object stores a reference to x for this simple test. Now x
> is always leaking. Furthermore OOP app is leaking (if I set it to
> call finalize and printf on finalize[] nothing happens).
>
> I can verify that if X is created somewhere in smalltalk function
> and going out of scope it is properly destroyed if not used and
> does not leak.
>
> If assigned to OOP app x leaks because OOP app is not freed. Most
> probably OOP app is simply not garbage collected in that short
> time?
>
> Is there a way to force garbage collection before shutting down?

You can call "ObjectMemory globalGarbageCollect".

If you want finalization (I assume you do, because otherwise the leak
is harmless), then even that is probably not enough, because
finalization is done asynchronously after GC finishes.  Why do you
absolutely need to finalize app?  What resources does it hold?

Paolo

>
>
>
> _______________________________________________ help-smalltalk
> mailing list [hidden email]
> https://lists.gnu.org/mailman/listinfo/help-smalltalk
>

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Roland Plüss-2


On 04/03/2015 10:24 PM, Paolo Bonzini wrote:

>
> On 03/04/2015 21:30, Roland Plüss wrote:
>> I'm trying to figure out why I've got a leak with GST. It's about a
>> C++ program hosting smalltalk as script language. Let's say you've
>> got this scenario:
>>
>> class Something: OOP app Init(): gst_initialize( NULL, NULL,
>> GST_NO_TTY ) // add classes and stuff app = gst_perform( classApp,
>> selectorNew ) // calls also init gst_register_oop( app );
>> CleanUp(): app = gst_perform( classApp, selectorCleanup ) // calls
>> cleanup gst_unregister_oop( app ); // clean up classes and stugg
>> gst_invoke_hook( GST_ABOUT_TO_QUIT )
>>
>> Furthermore let's say a smalltalk script does something simple like
>> this: MyApp subclass: App [ | x | init [ x := CEnabledClass new ]
>> cleanup [ x := nil ]
>>
>> No other object stores a reference to x for this simple test. Now x
>> is always leaking. Furthermore OOP app is leaking (if I set it to
>> call finalize and printf on finalize[] nothing happens).
>>
>> I can verify that if X is created somewhere in smalltalk function
>> and going out of scope it is properly destroyed if not used and
>> does not leak.
>>
>> If assigned to OOP app x leaks because OOP app is not freed. Most
>> probably OOP app is simply not garbage collected in that short
>> time?
>>
>> Is there a way to force garbage collection before shutting down?
> You can call "ObjectMemory globalGarbageCollect".
>
> If you want finalization (I assume you do, because otherwise the leak
> is harmless), then even that is probably not enough, because
> finalization is done asynchronously after GC finishes.  Why do you
> absolutely need to finalize app?  What resources does it hold?
>
> Paolo
The application holds C++ resources by reference counting outside
Smalltalk. The resources have to be cleaned up before the Smalltalk
module is shut down. This is because the engine keeps running valid with
the scripting module shut down (so you can start/stop it multiple
times). Without proper finalization the reference counts are off leading
to random crashes somewhere down the line.

--
Yours sincerely
Plüss Roland

Leader and Head Programmer
- Game: Epsylon ( http://www.indiedb.com/games/epsylon )
- Game Engine: Drag[en]gine ( http://www.indiedb.com/engines/dragengine
, http://dragengine.rptd.ch/wiki )
- Normal Map Generator: DENormGen ( http://epsylon.rptd.ch/denormgen.php )
- As well as various Blender export scripts und game tools


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Holger Freyther
On Fri, Apr 03, 2015 at 11:36:55PM +0200, Roland Plüss wrote:

> The application holds C++ resources by reference counting outside
> Smalltalk. The resources have to be cleaned up before the Smalltalk
> module is shut down. This is because the engine keeps running valid with
> the scripting module shut down (so you can start/stop it multiple
> times). Without proper finalization the reference counts are off leading
> to random crashes somewhere down the line.

In regard to leaks "allOwners" can be of help. The tooling is a
bit difficult but it can be interesting to see it.

Finalization/Shutdown. You should terminate all processes to some
degree and wait for the "finalization listener" to have executed
and shutdown everything.

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Roland Plüss-2


On 04/04/2015 06:21 PM, Holger Hans Peter Freyther wrote:

> On Fri, Apr 03, 2015 at 11:36:55PM +0200, Roland Plüss wrote:
>
>> The application holds C++ resources by reference counting outside
>> Smalltalk. The resources have to be cleaned up before the Smalltalk
>> module is shut down. This is because the engine keeps running valid with
>> the scripting module shut down (so you can start/stop it multiple
>> times). Without proper finalization the reference counts are off leading
>> to random crashes somewhere down the line.
> In regard to leaks "allOwners" can be of help. The tooling is a
> bit difficult but it can be interesting to see it.
>
> Finalization/Shutdown. You should terminate all processes to some
> degree and wait for the "finalization listener" to have executed
> and shutdown everything.
What you mean with shuting down all processes? As far as I know GST
knows only one process: the main process. When I'm outside the main
process should it not be the case that each call to gst_perform or
similar is conclusive, hence finishing up? So how would a finalization
listener work once you exit again the byte code? Similar how would
saving a snapshot work? There you have to also save the image and
somehow "exit" back into C++ land to shut down. Am I missing here something?

--
Mit freundlichen Grüssen
Plüss Roland

Leader und Head Programmer
- Game: Epsylon ( http://www.indiedb.com/games/epsylon )
- Game Engine: Drag[en]gine ( http://www.indiedb.com/engines/dragengine
, http://dragengine.rptd.ch/wiki )
- Normal Map Generator: DENormGen ( http://epsylon.rptd.ch/denormgen.php )
- Sowie verschiedene Blender Export-Skripts und Game-Tools


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Holger Freyther
On Sun, Apr 05, 2015 at 12:16:36AM +0200, Roland Plüss wrote:

> What you mean with shuting down all processes? As far as I know GST
> knows only one process: the main process. When I'm outside the main
> process should it not be the case that each call to gst_perform or
> similar is conclusive, hence finishing up? So how would a finalization
> listener work once you exit again the byte code? Similar how would
> saving a snapshot work? There you have to also save the image and
> somehow "exit" back into C++ land to shut down. Am I missing here something?

I am referring to Smalltalk processes that continue to run. With
spawning the "gst" application you have:

st> Process allInstancesDo: [:each | each printNl]
Process(nil at highIOPriority, terminated)
Process('finalization listener' at timingPriority, waiting on a semaphore)
Process('idle' at idlePriority, ready to run)
Process('delay process' at timingPriority, waiting on a semaphore)

So these processes run, they refer to objects. Now I don't know
how many objects you want to be collected but you need to give up
references and you need to make sure the finalization listener is
woken up and runs


'finalization listener' process:


    initialize [
        ...

        finalizerProcess :=
                [[gcSemaphore wait.  self startFinalizers] repeat]
                        forkAt: Processor timingPriority.
        ...
    ]


    startFinalizers [
        "Private - Fire a low-priority process to finalize the objects"
        <category: 'idle tasks'>
        | local localFinalizerProcess |
        local := gcArray.
        gcArray := nil.

        localFinalizerProcess := [:array | array do: [:each | each mourn]]
                    newProcessWith: {local}.
        localFinalizerProcess priority: Processor userSchedulingPriority.
        localFinalizerProcess name: 'finalization worker'.
        localFinalizerProcess resume
    ]


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Roland Plüss-2


On 04/05/2015 01:38 PM, Holger Hans Peter Freyther wrote:

> On Sun, Apr 05, 2015 at 12:16:36AM +0200, Roland Plüss wrote:
>
>> What you mean with shuting down all processes? As far as I know GST
>> knows only one process: the main process. When I'm outside the main
>> process should it not be the case that each call to gst_perform or
>> similar is conclusive, hence finishing up? So how would a finalization
>> listener work once you exit again the byte code? Similar how would
>> saving a snapshot work? There you have to also save the image and
>> somehow "exit" back into C++ land to shut down. Am I missing here something?
> I am referring to Smalltalk processes that continue to run. With
> spawning the "gst" application you have:
>
> st> Process allInstancesDo: [:each | each printNl]
> Process(nil at highIOPriority, terminated)
> Process('finalization listener' at timingPriority, waiting on a semaphore)
> Process('idle' at idlePriority, ready to run)
> Process('delay process' at timingPriority, waiting on a semaphore)
>
> So these processes run, they refer to objects. Now I don't know
> how many objects you want to be collected but you need to give up
> references and you need to make sure the finalization listener is
> woken up and runs
>
>
> 'finalization listener' process:
>
>
>     initialize [
>         ...
>
>         finalizerProcess :=
>                 [[gcSemaphore wait.  self startFinalizers] repeat]
>                         forkAt: Processor timingPriority.
>         ...
>     ]
>
>
>     startFinalizers [
>         "Private - Fire a low-priority process to finalize the objects"
>         <category: 'idle tasks'>
>         | local localFinalizerProcess |
>         local := gcArray.
>         gcArray := nil.
>
>         localFinalizerProcess := [:array | array do: [:each | each mourn]]
>                     newProcessWith: {local}.
>         localFinalizerProcess priority: Processor userSchedulingPriority.
>         localFinalizerProcess name: 'finalization worker'.
>         localFinalizerProcess resume
>     ]
>
So I need to run this 'finalization listener' process somehow and this
cleans up? How would I trigger this from C++? And as a follow up
question would it not be better to just call a full garbage collection
run? After all there is only supposed to be one application object
holding all the script sources one way or the other. I drop the
reference of this one at exit time so a garbage collector run should
clean all up properly. How can I run such a fill garbage collection from
C++?

--
Mit freundlichen Grüssen
Plüss Roland

Leader und Head Programmer
- Game: Epsylon ( http://www.indiedb.com/games/epsylon )
- Game Engine: Drag[en]gine ( http://www.indiedb.com/engines/dragengine
, http://dragengine.rptd.ch/wiki )
- Normal Map Generator: DENormGen ( http://epsylon.rptd.ch/denormgen.php )
- Sowie verschiedene Blender Export-Skripts und Game-Tools


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Holger Freyther
On Sun, Apr 05, 2015 at 05:41:31PM +0200, Roland Plüss wrote:

> So I need to run this 'finalization listener' process somehow and this
> cleans up? How would I trigger this from C++? And as a follow up
> question would it not be better to just call a full garbage collection
> run? After all there is only supposed to be one application object
> holding all the script sources one way or the other. I drop the
> reference of this one at exit time so a garbage collector run should
> clean all up properly. How can I run such a fill garbage collection from
> C++?

I don't think you can easily trigger this from C/C++. The full
shutdown requirement is nothing we had sofar. I am just telling
you what we have and hope you can fill-in the blanks.

In C there is "_gst_global_gc" at the end it will run the
mournn_objects() function. This will schedule calling "gcSemaphore
signal" on the semaphore used by the "finalization listener". This
means the "finalization listener" Smalltalk process will be runnable
again and will be executed at some point in time. The finalization
listener will run worker code to mourn more objects. Now the listener
does not know when the "localFinalizeProcess" is done or how many
of them still run.


Easy: Trigger a global garbage collect

st> ObjectMemory globalGarbageCollect

Harder: Wait for finalization listener to be done.

E.g. you can put a "count" in ProcSched.st (you need to
patch libgst/dict.c with the new member too) to see how
often it executed... or executed last.


Harder: You need to keep track how many finalization
workers were spawned and if they have exited.



The other question. If you know which kind of objects
hold references you want to finalize and you have decided
you want to give them up. Why don't you trigger this cleanup
from your code?

 MyBindingBaseClass allSubinstancesDo: [:each | each dispose ].


holger

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Roland Plüss-2


On 04/06/2015 06:41 PM, Holger Hans Peter Freyther wrote:

> On Sun, Apr 05, 2015 at 05:41:31PM +0200, Roland Plüss wrote:
>
>> So I need to run this 'finalization listener' process somehow and this
>> cleans up? How would I trigger this from C++? And as a follow up
>> question would it not be better to just call a full garbage collection
>> run? After all there is only supposed to be one application object
>> holding all the script sources one way or the other. I drop the
>> reference of this one at exit time so a garbage collector run should
>> clean all up properly. How can I run such a fill garbage collection from
>> C++?
> I don't think you can easily trigger this from C/C++. The full
> shutdown requirement is nothing we had sofar. I am just telling
> you what we have and hope you can fill-in the blanks.
>
> In C there is "_gst_global_gc" at the end it will run the
> mournn_objects() function. This will schedule calling "gcSemaphore
> signal" on the semaphore used by the "finalization listener". This
> means the "finalization listener" Smalltalk process will be runnable
> again and will be executed at some point in time. The finalization
> listener will run worker code to mourn more objects. Now the listener
> does not know when the "localFinalizeProcess" is done or how many
> of them still run.
>
>
> Easy: Trigger a global garbage collect
>
> st> ObjectMemory globalGarbageCollect
>
> Harder: Wait for finalization listener to be done.
>
> E.g. you can put a "count" in ProcSched.st (you need to
> patch libgst/dict.c with the new member too) to see how
> often it executed... or executed last.
>
>
> Harder: You need to keep track how many finalization
> workers were spawned and if they have exited.
>
>
>
> The other question. If you know which kind of objects
> hold references you want to finalize and you have decided
> you want to give them up. Why don't you trigger this cleanup
> from your code?
>
>  MyBindingBaseClass allSubinstancesDo: [:each | each dispose ].
>
>
> holger
I'm using a similar trick in my own scripting language. Hoped I can get
away in Smalltalk without it. It's certainly a working solution albeit
not the most good one. Should do the trick for the time being.

--
Mit freundlichen Grüssen
Plüss Roland

Leader und Head Programmer
- Game: Epsylon ( http://www.indiedb.com/games/epsylon )
- Game Engine: Drag[en]gine ( http://www.indiedb.com/engines/dragengine
, http://dragengine.rptd.ch/wiki )
- Normal Map Generator: DENormGen ( http://epsylon.rptd.ch/denormgen.php )
- Sowie verschiedene Blender Export-Skripts und Game-Tools


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Holger Freyther
On Tue, Apr 07, 2015 at 06:18:13PM +0200, Roland Plüss wrote:

> I'm using a similar trick in my own scripting language. Hoped I can get
> away in Smalltalk without it. It's certainly a working solution albeit
> not the most good one. Should do the trick for the time being.

Okay, what else do you think the VM can do? E.g. if I would
implement a "shutdown" command I would suspend all processes,
then run the global collection, then look at gcArray iterate
over them to call mourn.

"Stop the normal handling"
proc := (Process allInstances select: [:each |
                each name = 'finalization listener']) first suspend

"Check if other finalizers run or wait..This runs the risk if
new garbage is produced.. the vm will be upset and aborts.."
[(Process allInstances select: [:each | each name = 'finalization worker']) isEmpty]
        whileFalse: [Processor yield]


"Run GC which will signal finalization.."
ObjectMemory globalGarbageCollect

"Take the to be finalized array and mourn"
garbage := Processor instVarNamed: #gcArray
garbage ifNotNil: [garbage do: [:each | each mourn]]


Specially step 1 and 2 is a bit dangerous. You should suspend
other processes/work too to prevent from more GC to be produced.

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Roland Plüss-2


On 04/07/2015 07:22 PM, Holger Hans Peter Freyther wrote:

> On Tue, Apr 07, 2015 at 06:18:13PM +0200, Roland Plüss wrote:
>
>> I'm using a similar trick in my own scripting language. Hoped I can get
>> away in Smalltalk without it. It's certainly a working solution albeit
>> not the most good one. Should do the trick for the time being.
> Okay, what else do you think the VM can do? E.g. if I would
> implement a "shutdown" command I would suspend all processes,
> then run the global collection, then look at gcArray iterate
> over them to call mourn.
>
> "Stop the normal handling"
> proc := (Process allInstances select: [:each |
> each name = 'finalization listener']) first suspend
>
> "Check if other finalizers run or wait..This runs the risk if
> new garbage is produced.. the vm will be upset and aborts.."
> [(Process allInstances select: [:each | each name = 'finalization worker']) isEmpty]
> whileFalse: [Processor yield]
>
>
> "Run GC which will signal finalization.."
> ObjectMemory globalGarbageCollect
>
> "Take the to be finalized array and mourn"
> garbage := Processor instVarNamed: #gcArray
> garbage ifNotNil: [garbage do: [:each | each mourn]]
>
>
> Specially step 1 and 2 is a bit dangerous. You should suspend
> other processes/work too to prevent from more GC to be produced.
This is indeed a problem I've seen already too. But how does Squeak for
example go about it? It does properly work with shutting down and
finalizing objects when the VM goes out. What do they do to solve the
problem?

--
Mit freundlichen Grüssen
Plüss Roland

Leader und Head Programmer
- Game: Epsylon ( http://www.indiedb.com/games/epsylon )
- Game Engine: Drag[en]gine ( http://www.indiedb.com/engines/dragengine
, http://dragengine.rptd.ch/wiki )
- Normal Map Generator: DENormGen ( http://epsylon.rptd.ch/denormgen.php )
- Sowie verschiedene Blender Export-Skripts und Game-Tools


_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

signature.asc (188 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: OOP leaking with registered object

Paolo Bonzini-2


On 08/04/2015 13:36, Roland Plüss wrote:
>>> Specially step 1 and 2 is a bit dangerous. You should suspend
>>> other processes/work too to prevent from more GC to be
>>> produced.
> This is indeed a problem I've seen already too. But how does Squeak
> for example go about it? It does properly work with shutting down
> and finalizing objects when the VM goes out. What do they do to
> solve the problem?

I don't think Squeak will finalize all objects when the VM is shutdown.

Paolo

_______________________________________________
help-smalltalk mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-smalltalk