Bug 21900 - calling GTK.Application.Invoke more than once in non-gui thread leaks memory
Summary: calling GTK.Application.Invoke more than once in non-gui thread leaks memory
Status: NEW
Alias: None
Product: Gtk#
Classification: Mono
Component: gtk-sharp ()
Version: 2.x
Hardware: Other Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2014-08-07 01:57 UTC by Chris Spurrier
Modified: 2014-08-07 01:57 UTC (History)
1 user (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report for Bug 21900 on GitHub or Developer Community if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: GitHub Markdown or Developer Community HTML
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
NEW

Description Chris Spurrier 2014-08-07 01:57:16 UTC
After testing an embedded Linux application which was slowly leaking memory I figured out how to profile my Mono application and found what I am pretty sure is a memory leak. If GTK.Application.Invoke wraps a section of code in a non-gui thread more than once, it will leak Glib.Timeout.TimeoutProxy objects. This was caught by invoking mono with --profile=log:heapshot which will grab a heap snap shot each time garbage is collected. After 50 or so heap snap shots, the Glib.Timeout.TimeoutProxy object count bubbled to the top of the list in object count. I used heap-shot to view the output.mlpd file. When only one GTK.Application.Invoke was used, the problem went away. After 100s of heap snap shots, all object counts were the same, so everything was being collected. I have been up all night trying to fix this, so I have blown away the output.mlpd file with the leak, and it is on an embedded ARM device and I will try to induce the error again at a later time. But for now the following code would cause the issue:

    protected void WorkThread()
    {
        int WorkerCnt = 1;
        
        while (false == _stopWorker)
        {
            try
            { 
                if (false != EventNotify.Upate)
                {   
                    EventNotify.Upate = false;
                    WorkerCnt = WORKER_THREAD_CNT;
                    
                    Application.Invoke(delegate
                    {
                        PrintNotify();
                    });
                }
                else if (0 == --WorkerCnt)
                {
                    WorkerCnt = WORKER_THREAD_CNT;
                    EventNotify.ReEnable();
                
                    Application.Invoke(delegate
                    {
                        PrintDateTime();
                    });
                }
            
                Application.Invoke(delegate
                {
                    HomeRefresh();
                });
                    
                Application.Invoke(delegate
                {
                    MonitorPlayer();
                });
                
                Application.Invoke(delegate
                {
                    UpdateMemStats();
                });
                
                Thread.Sleep(WORKER_THREAD_TICK_RATE_MS); // 1000ms
            }
            catch
            {
            
            }
        }
    }


and doing as follows removed the leak:

    protected void WorkThread()
    {
        int WorkerCnt = 1;
        
        while (false == _stopWorker)
        {
            try
            {
                Application.Invoke(delegate
                {
                    if (false != EventNotify.Upate)
                    {   
                        EventNotify.Upate = false;
                        WorkerCnt = WORKER_THREAD_CNT;
                        PrintNotify();
                    }
                    else if (0 == --WorkerCnt)
                    {
                        WorkerCnt = WORKER_THREAD_CNT;
                        EventNotify.ReEnable();
                    
                        PrintDateTime();
                    }
                
                    HomeRefresh();
                    MonitorPlayer();
                    UpdateMemStats();
                });
                
                Thread.Sleep(WORKER_THREAD_TICK_RATE_MS); // 1000ms
            }
            catch
            {
            
            }
        }
    }

This is my first time using GTK#, Mono, and Linux for that matter so I am not an expert by any means. But I do know this fixed the issue, and I have no idea if this is documented not to do somewhere, but after searching for days, I found nothing so I am capturing it here.

More information:
gtk-sharp version 2.12.0
Mono 3.2.8 testing from Jessie running on Wheezy
Linux version (embedded ARM SBC):
Linux ts4712-488f65 2.6.34-ts471x-gd17a9cc #47 PREEMPT Wed Apr 30 08:17:30 MST 2014 armv5tejl GNU/Linux