Truly bizarre - XmlSerializer + ADO.NET = Thread Handle leak?

  • Thread starter Thread starter Nick Farina
  • Start date Start date
N

Nick Farina

After two days of debugging, I have finally discovered a very odd bug when
using the XmlSerializer object and the SqlConnection object. It seems that
if you instantiate an XmlSerializer object before opening a connection to a
SQL database, then all future Thread objects created in the entire program
will not be garbage collected.

Since my application is a TCP server, it is constantly creating threads
using the Thread object. If I let it run for a couple days, and watch the
Handle count in the Task Manager (click View...Select Columns...) or even
better, SysInternal's Process Explorer, the thread handle count will get
well above 200,000. Eventually the app runs out of memory.

I'm using the 1.1 framework. Try this sample code below and see for
yourself (compile as a console app):

class Class1
{
[STAThread]
static void Main(string[] args)
{
// any valid database connect string
string dbConnectString = "replace this with your DB connect string";
SqlConnection db = new SqlConnection(dbConnectString);

Console.WriteLine("Press enter to start...");
Console.ReadLine();

// All you need to do is instantiate the XmlSerializer to produce
the problem.
// If you switch the next two lines, the problem goes away!
XmlSerializer xs = new XmlSerializer(typeof(object));
db.Open(); db.Close();

// create and finish a bunch of thread objects
for (int x=0;x<100;x++)
{
Thread myThread = new Thread(new ThreadStart(DoNothing));
myThread.Start();
myThread.Join();
}

// this should clean up all thread objects (and therefore, handles)
GC.Collect();

Console.WriteLine("Press enter to exit...");
Console.ReadLine();
}

static void DoNothing(){}
}

If you compile and run the above class, then watch its process, it will
allocate approximately 570 system handles and never release them.

Obviously, the workaround is to open up a connection to the database before
using the XmlSerializer. But unfortunately, I'm using the XmlSerializer to
parse an XML app configuration file which contains the DB connect string
itself. Chicken-and-egg you might say.

nick

=====================
Nick Farina
CTO
Spotlight Mobile, Inc.
=====================
 
Try doing this GC.WaitForPendingFinalizers(). This call will force all
finalizers to run before continuing. Looks the v1.1 is not very aggressive
in collecting these handles.

HTH
_RIck
--------------------
| From: "Nick Farina" <n a r i n @ v o y a g e r . n e t>
| Newsgroups: microsoft.public.dotnet.framework
| Subject: Truly bizarre - XmlSerializer + ADO.NET = Thread Handle leak?
| Lines: 68
| X-Priority: 3
| X-MSMail-Priority: Normal
| X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
| X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1165
| Message-ID: <odI7b.408541$Ho3.61818@sccrnsc03>
| NNTP-Posting-Host: 12.224.49.189
| X-Complaints-To: (e-mail address removed)
| X-Trace: sccrnsc03 1063210964 12.224.49.189 (Wed, 10 Sep 2003 16:22:44
GMT)
| NNTP-Posting-Date: Wed, 10 Sep 2003 16:22:44 GMT
| Organization: Comcast Online
| Date: Wed, 10 Sep 2003 16:22:44 GMT
| Path:
cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!newsfeed00.sul.t-online.de!t-onlin
e.de!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!wn14feed!wn13feed!world
net.att.net!204.127.198.203!attbi_feed3!attbi.com!sccrnsc03.POSTED!not-for-m
ail
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework:53389
| X-Tomcat-NG: microsoft.public.dotnet.framework
|
| After two days of debugging, I have finally discovered a very odd bug when
| using the XmlSerializer object and the SqlConnection object. It seems
that
| if you instantiate an XmlSerializer object before opening a connection to
a
| SQL database, then all future Thread objects created in the entire program
| will not be garbage collected.
|
| Since my application is a TCP server, it is constantly creating threads
| using the Thread object. If I let it run for a couple days, and watch the
| Handle count in the Task Manager (click View...Select Columns...) or even
| better, SysInternal's Process Explorer, the thread handle count will get
| well above 200,000. Eventually the app runs out of memory.
|
| I'm using the 1.1 framework. Try this sample code below and see for
| yourself (compile as a console app):
|
| class Class1
| {
| [STAThread]
| static void Main(string[] args)
| {
| // any valid database connect string
| string dbConnectString = "replace this with your DB connect
string";
| SqlConnection db = new SqlConnection(dbConnectString);
|
| Console.WriteLine("Press enter to start...");
| Console.ReadLine();
|
| // All you need to do is instantiate the XmlSerializer to produce
| the problem.
| // If you switch the next two lines, the problem goes away!
| XmlSerializer xs = new XmlSerializer(typeof(object));
| db.Open(); db.Close();
|
| // create and finish a bunch of thread objects
| for (int x=0;x<100;x++)
| {
| Thread myThread = new Thread(new ThreadStart(DoNothing));
| myThread.Start();
| myThread.Join();
| }
|
| // this should clean up all thread objects (and therefore,
handles)
| GC.Collect();
|
| Console.WriteLine("Press enter to exit...");
| Console.ReadLine();
| }
|
| static void DoNothing(){}
| }
|
| If you compile and run the above class, then watch its process, it will
| allocate approximately 570 system handles and never release them.
|
| Obviously, the workaround is to open up a connection to the database
before
| using the XmlSerializer. But unfortunately, I'm using the XmlSerializer
to
| parse an XML app configuration file which contains the DB connect string
| itself. Chicken-and-egg you might say.
|
| nick
|
| =====================
| Nick Farina
| CTO
| Spotlight Mobile, Inc.
| =====================
|
|
|
 
Back
Top