Memory leak in .NET service on Windows 2000

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

We appear to have identified a memory leak in the .NET Framework using a service running on Windows 2000 platforms

Using the .NET Development Environment we have created a standard C# Windows Service and added a FileSystemWatcher and a Timer object. When the timer fires (every 30-seconds), the FileSystemWatcher is temporarily disabled and this causes a significant memory leak on Windows 2000 platforms (approx 10Kbytes every time)
The problem does not seem to occur on Windows XP platforms
We have also found that the leak does not occur on Windows 2000 platforms when running a C# Windows applicatio
instead of a service (i.e. using System.Windows.Forms.Timer instead of System.Timers.Timer)

Has anyone else experienced anything like this?
 
I've seen timer leaks especially with short durations like yours but it was
always a code issue and not an OS issue. What are you doing inside your
timer with objects and resources?
 
For what it is worth, the timer runs on it's own thread, and you are
creating the FileSystemWatcher from the main thread. When running the
Windows app that works, as you explained earlier, the timer runs on the main
thread as well.
So I would create the FileSystemWatcher from the timer the first time it
expires (hoping that the timer is serviced by the same thread every time - I
haven't checked it), and see what happens.

Rob said:
Couldn't be simpler. I can create a brand new .NET C# service where the
OnStart function does the following to create a FileSystemWatcher and a
timer:
//Initialise the folder monitor
m_FolderMonitor = new System.IO.FileSystemWatcher();
m_FolderMonitor.BeginInit();
m_FolderMonitor.EnableRaisingEvents = true;
m_FolderMonitor.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
m_FolderMonitor.Path = "C:\\Temp\\Empty"; // Folder containing no files
m_FolderMonitor.Created += new System.IO.FileSystemEventHandler(FolderMonitorEventHandler);
m_FolderMonitor.EndInit();

//Initialise the 30-second timer
m_Timer = new System.Timers.Timer();
m_Timer.BeginInit();
m_Timer.AutoReset = true;
m_Timer.Interval = (30 * 1000);
m_Timer.Enabled = true;
m_Timer.Elapsed += new System.Timers.ElapsedEventHandler(m_Timer_Elapsed);
m_Timer.EndInit();

The FileSystemWatcher does nothing because the folder it's monitoring is
always empty. The timer fires every 30 seconds and invokes the following:
// Invoked every time the 30-second timer expires
private void m_Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// Here we want to disable both the folder monitor & timer events so that
they do not occur while we are in this handler function,
// however the following line which turns off the folder monitor event
causes a leak on Windows 2000 platforms!
m_FolderMonitor.EnableRaisingEvents = false;

// Turn off the timer (commented out to show this is not the source of the memory leak)
// m_Timer.Enabled = false;

// Do some time-consuming processing...

// Turn the events back on again
m_FolderMonitor.EnableRaisingEvents = true;
// (commented out to show this is not the source of the memory leak)
// m_Timer.Enabled = true;
}

so all we're doing is disabling and re-enabling the FileSystemWatcher. I'd
be interested in your thoughts!
 
No such luck. Putting the following code in the timer handler so that the FileSystemWatcher is created in the timer thread makes no difference - Private Bytes keeps on climbing every 30 seconds:

private void m_Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (!m_bFolderMonitorCreated)
{
m_FolderMonitor = new System.IO.FileSystemWatcher();
m_FolderMonitor.BeginInit();
m_FolderMonitor.EnableRaisingEvents = true;
m_FolderMonitor.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite;
m_FolderMonitor.Path = "C:\\Temp\\Empty"; // Folder containing no files
m_FolderMonitor.Created += new System.IO.FileSystemEventHandler(FolderMonitorEventHandler);
m_FolderMonitor.EndInit();
m_bFolderMonitorCreated = true;
}
When running the Windows app that works, as you explained earlier,
the timer runs on the main thread as well.
I'm not sure I follow you here. The windows app does exactly the same as the service, creating the FileSystemWatcher and Timer objects when a Start button is pressed, and disabling & re-enabling the FileSystemWatcher from within the Timer handler, yet there is no memory leak in this case.
 
this guy m_FolderMonitor, where is he de-allocated?
in EndInit()? If not, you create a new object everytime the timer goes off
without cleaning it out.
 
this guy m_FolderMonitor, where is he de-allocated? in EndInit()
If not, you create a new object everytime the timer goes off without cleaning it out

This is a tiny sample program to demonstrate a problem so the FileSystemWatcher watcher object m_FolderMonitor is never specifically deallocated, however a new object is *not* created every time the timer goes off but only a single instance is ever created
Initially this single instance was created in the service's OnStart function, but following Chris's suggestion to "create the FileSystemWatcher from the timer the first time it expires", I now do just that (not that this has made any difference to the memory usage) - notice below how the new FileSystemWatcher is only allocated on the first Timer event
 
Rob, I have a windows service running with a timer extracting data from
remote SQL Servers.
The private bytes sometimes go up to 15,900,000 but then it comes down to
13,700,000 and it fluctuates between these values. Is this not what you are
experiencing?
If not, then what happens if you do not touch the watcher from the timer, is
the problem still there? I am just thinking that in your original example
you said "Do some time-consuming processing...", the problem won't be there?
To test this, my "time consuming processing" would be something like to
sleep for a second or two.
If all else fail, then maybe you should use a sync object like a Mutex to
sync processing between the timer and the watcher.

Rob said:
cleaning it out.

This is a tiny sample program to demonstrate a problem so the
FileSystemWatcher watcher object m_FolderMonitor is never specifically
deallocated, however a new object is *not* created every time the timer goes
off but only a single instance is ever created.
Initially this single instance was created in the service's OnStart
function, but following Chris's suggestion to "create the FileSystemWatcher
from the timer the first time it expires", I now do just that (not that this
has made any difference to the memory usage) - notice below how the new
FileSystemWatcher is only allocated on the first Timer event:
 
Rob, I have a windows service running with a timer extracting data from remote SQL Servers
The private bytes sometimes go up to 15,900,00
but then it comes down to 13,700,000 and it fluctuates between these values
Is this not what you are experiencing
No, private bytes goes up when the watcher is disabled (every 30 seconds); it comes down a few seconds later (presumably as a result of garbage collection) but not all the way, averaging about 10,000 bytes higher than it was. if I set perfmon to monitor at 30-second intervals (same as the timer) I see a straight line going ever upwards. If I leave the service running overnight or over a weekend it reaches 100's of Mb and no doubt would eventually grind the system to a halt
If not, then what happens if you do not touch the watcher from the timer, is the problem still there
I am just thinking that in your original example you said "Do some time-consuming processing...", the problem won't be there
To test this, my "time consuming processing" would be something like to sleep for a second or two
No, if I comment out the line in the timer handler which disables the watcher, then the memory stays absolutely level and never goes up at all
I can do whatever else I like in the timer (like sleeping) but the private bytes won't go up unless I disable & re-enable the FileSystemWatcher
If all else fail, then maybe you should use a sync object like a Mutex t
sync processing between the timer and the watcher
Yes, I've already re-engineered our live service not to use a timer. Now the event handler for the FileSystemWatcher just sets an event and a separate thread does timed waits on this event (as well as on a service shutdown event). If the watcher event is signalled we run the code to process the file reported by the watcher, and if the wait times out we do the code which used to be in the timer handler. This separate thread keeps doing timed waits on the watcher event until shutdown is signalled. This is fine as a workaround, but as this is our first usage of .NET for live products, we wanted to know whether we can trust .NET memory management for our current developments.
 
Back
Top