Memory leak in compiled exe when using timers

Ask questions about creating Graphical User Interfaces (GUI) in PowerShell and using WinForms controls.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
This topic is 7 years and 11 months old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked
User avatar
brinkcm
Posts: 25
Last visit: Mon Mar 09, 2020 6:18 am

Memory leak in compiled exe when using timers

Post by brinkcm »

Product, version and build: Powershell Studio 5.2.118
32 or 64 bit version of product: 64
Operating system: W7
32 or 64 bit OS: 64
PowerShell Version: 4

Similar to this topic:
viewtopic.php?t=6104

My compiled exe is dying after a day or two, and the more timers I add the faster it dies. Willing to work with support to whatever extent is necessary. Here's an example of the application event log's entry at time of crash.


Source: NET Runtime
EventID: 1026

Application: CSMON.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.OutOfMemoryException
at System.RuntimeTypeHandle.GetInstantiation(System.RuntimeTypeHandle, System.Runtime.CompilerServices.ObjectHandleOnStack, Boolean)
at System.RuntimeType.GetGenericArgumentsInternal()
at System.RuntimeType.MakeGenericType(System.Type[])
at System.Runtime.CompilerServices.CallSite.Create(System.Type, System.Runtime.CompilerServices.CallSiteBinder)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitDynamicExpression(System.Linq.Expressions.Expression)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpression(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpressionAsVoid(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.Emit(System.Linq.Expressions.BlockExpression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpressionAsVoid(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.Emit(System.Linq.Expressions.BlockExpression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitBlockExpression(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpression(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitTryExpression(System.Linq.Expressions.Expression)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpression(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpressionAsVoid(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.Emit(System.Linq.Expressions.BlockExpression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitBlockExpression(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpression(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitTryExpression(System.Linq.Expressions.Expression)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpression(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpressionAsVoid(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.Emit(System.Linq.Expressions.BlockExpression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitExpressionAsVoid(System.Linq.Expressions.Expression, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitLambdaBody(System.Linq.Expressions.Compiler.CompilerScope, Boolean, CompilationFlags)
at System.Linq.Expressions.Compiler.LambdaCompiler.EmitLambdaBody()
at System.Linq.Expressions.Compiler.LambdaCompiler.Compile(System.Linq.Expressions.LambdaExpression, System.Runtime.CompilerServices.DebugInfoGenerator)
at System.Management.Automation.Interpreter.LightDelegateCreator.Compile(System.Object)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
User avatar
davidc
Posts: 5913
Last visit: Mon Jul 08, 2019 8:55 am
Been upvoted: 2 times

Re: Memory leak in compiled exe when using timers

Post by davidc »

[TOPIC MOVED TO POWERSHELL GUI FORUM]

Without a script it is hard to tell what exactly is happening.

The timer is part of .NET library and the package is simply a host you would probably get the same result in the console. You might want to force garbage collection every once in a while and see if it helps:
  1. [System.GC]::Collect()
David
David
SAPIEN Technologies, Inc.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Memory leak in compiled exe when using timers

Post by jvierra »

GC will not he in this situation. The usual cause is a re-entrant time. When entering the tick we should disable the timer and then re-enable it on exit of the tick. If the timer needs to do substantial work then you should schedule a job in the tick.

Long running timers should be set to the longest interval needed. If we want to check every 5 seconds then set the timer for 5 seconds. The default is 100ms which is to short form most things.

Be careful about creating global collections. Also note that calls to third party assemblies can cause leaks.
User avatar
davidc
Posts: 5913
Last visit: Mon Jul 08, 2019 8:55 am
Been upvoted: 2 times

Re: Memory leak in compiled exe when using timers

Post by davidc »

You beat me to the punch on the enable / disable. This allows the the objects to freed so they can be collected by the garbage collector.

David
David
SAPIEN Technologies, Inc.
User avatar
brinkcm
Posts: 25
Last visit: Mon Mar 09, 2020 6:18 am

Re: Memory leak in compiled exe when using timers

Post by brinkcm »

This is a form project in PSH Studio. How would you like to see the script? I can submit a support ticket and attach the exported file.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Memory leak in compiled exe when using timers

Post by jvierra »

David, I have found by trial that the timer is being reentered while code is executing blocks the previous execution in mid-stream. This can pile up and cause a lockup or a memory leak. The rate of leak is dependent on the frequency of re-execution. Disabling the timer prevents this. If the code is trivial then this will not happen. Longer blocks of timer tick code are a problem.

MS has always warned about timers. SharePoint has a whole service dedicated to timers so that the threads can be managed on large systems.

Local timers in compiled code are used to launch a thread which prevents re-entrant corruption. In PowerShell we can use runspaces and jobs.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Memory leak in compiled exe when using timers

Post by jvierra »

brinkcm wrote:This is a form project in PSH Studio. How would you like to see the script? I can submit a support ticket and attach the exported file.
Just paste the timer tick code at first. You can add it as an attachment in this forum on your post. select the advanced editor and not the quick editor.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Memory leak in compiled exe when using timers

Post by jvierra »

brinkcm wrote:This is a form project in PSH Studio. How would you like to see the script? I can submit a support ticket and attach the exported file.
Just paste the timer tick code at first. You can add it as an attachment in this forum on your post. select the advanced editor and not the quick editor.
User avatar
davidc
Posts: 5913
Last visit: Mon Jul 08, 2019 8:55 am
Been upvoted: 2 times

Re: Memory leak in compiled exe when using timers

Post by davidc »

I've made a habit of disabling the timer, just in case the tick event is slowed do to a long script.

I should make a note to add the tip to the Spotlight on the Timer article.


brinkcm,

Try the disabling and enabling the timer in the tick event and see if that helps.

Note: The ticketing system is for product issues only and this forum is the best place for scripting questions.

David
David
SAPIEN Technologies, Inc.
User avatar
brinkcm
Posts: 25
Last visit: Mon Mar 09, 2020 6:18 am

Re: Memory leak in compiled exe when using timers

Post by brinkcm »

When you say disable/enable, do you mean setting Enabled property or calling Stop()/Start()? I understand that the timer would be halted at the beginning of tick processing and started at the end of tick processing.
This topic is 7 years and 11 months old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked