Re: GC and active sockets, and Pinned Memory
- From: "Willy Denoyette [MVP]" <willy.denoyette@xxxxxxxxxx>
- Date: Thu, 12 May 2005 00:11:53 +0200
Objects don't go out of scope, references do go out of scope.
Your local references go out of scope, but as YOU passed a NetworkStream
reference to the BeginRead delegate which posts a request to the completion
thread pool which stores the NetworkStream reference for later use, you have
yet another reference to the NetworkStream Object ( and as such to the
TcpClient and the Socket instances), so the GC can't collect. At this point
YOU say he! this is a "bad programming habit" I would like the GC to
consider the NS object as garbage, I say "it's a bug in your code" and the
GC can't and isn't supposed to protect you from bugs in your code.
When you're done with the TcpClient, you simply have to close it by calling
TcpClient.Close(), this will effectively remove the request from the pool,
close the socket (Dispose) the NetworkStream (Dispose) and the TcpClient
objects.
Willy.
"Arthur M." <ArthurM@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:4A7BEDB0-6D7B-4EA5-81E6-DAE9308A53C4@xxxxxxxxxxxxxxxx
> That was exactly my point; once an object goes out of scope and
> effectively
> is unreachable through any means available to developer, the only
> reference
> point to that object is a blocking IOCP thread.
>
> I agree that from pure system's point of view everything works properly,
> reference A goes away but reference B is still there. From development
> stand
> point of view, however, once i place something into IOCP pool there is no
> way
> for me to signal interrupt therefore, there is a logical assumption that
> if i
> remove all references to the object and the only one remains is IOCP
> reference, it should get garbage collected. Granted, leaving objects out
> of
> scope without clean up is bad programming habbit as is, but isn't garbage
> collection supposed to protect against those type of mistakes?
>
> I think:
> ( no refernce = garbage) equally (no reference = there is no way for a
> developer to access an object) and therefore (no way for a developer to
> access an object = garbage)
>
> Whether it is an adjustment to GC or adjustment to IOCP implementation
> (give
> me an ability to get BeginXXX operation out of wait state) is question
> someone in Microsoft (in my opinion) needs to ask and answer.
>
>
>
>
> "Willy Denoyette [MVP]" wrote:
>
>>
>> "Arthur M." <ArthurM@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
>> news:58AAC4AA-ED30-4F5C-B341-84F95120F024@xxxxxxxxxxxxxxxx
>> > In my specific case there is a socket server listenting on port 1111,
>> > you
>> > can
>> > use anything that accepts a connection.
>> >
>> > Note that function openConnections() never really closes a tcp client,
>> > but
>> > instead lets them go out of scope.
>> >
>> > Granted in true production environment this should never happen,
>> > however,
>> > garbage collection should prevent exactly that - memory/resource leak.
>> >
>> > My original code involves working directly with sockets, to ensure it
>> > is
>> > not
>> > my mistake, I have reproduced it with .NETs internal TCPClient hence no
>> > try/catch no watches for shutdowns and buffers that are thrown away
>> >
>> > Garbage collection timer is there to ensure garbage collection is
>> > forced
>> > to
>> > run.
>> >
>> > Code Below:
>> >
>> >
>> > static void openConnections()
>> > {
>> > for ( int op_counter = 0; op_counter < 30; op_counter++ )
>> > {
>> > System.Net.Sockets.TcpClient pt = new
>> > System.Net.Sockets.TcpClient();
>> > Singularity.Communication.Client(System.Net.IPAddress.Any, 0,
>> > System.Net.IPAddress.Loopback, 1111);
>> > pt.Connect(new
>> > System.Net.IPEndPoint(System.Net.IPAddress.Loopback, 1111));
>> > System.Net.Sockets.NetworkStream ns = pt.GetStream();
>> > ns.BeginRead(new byte[100], 1, 0, rcvd, ns);
>> >
>> > }
>> > }
>> >
>> > static void rcvd(IAsyncResult ar)
>> > {
>> > ((System.Net.Sockets.NetworkStream)
>> > (ar.AsyncState)).EndRead(ar);
>> > ( (System.Net.Sockets.NetworkStream) ( ar.AsyncState )
>> > ).BeginRead(new byte[100], 1, 0, rcvd, (
>> > (System.Net.Sockets.NetworkStream) (
>> > ar.AsyncState ) ));
>> > }
>> >
>> > static Timer tmr = new Timer();
>> >
>> > static void Main()
>> > {
>> > tmr.Interval = 1000;
>> > tmr.Enabled = true;
>> > tmr.Start();
>> > tmr.Tick += new EventHandler(tmr_Tick);
>> > //f.Show();
>> > //f.FormClosed += new FormClosedEventHandler(f_FormClosed);
>> > //f = null;
>> > openConnections();
>> > Application.Run();
>> > }
>> >
>> > static void tmr_Tick(object sender, EventArgs e)
>> > {
>> > Console.WriteLine("Collecting");
>> > tmr.Stop();
>> > GC.Collect();
>> > GC.WaitForPendingFinalizers();
>> > tmr.Start();
>> > }
>> >
>> >
>>
>>
>> While ns goes out of scope in openConnections it is passed to BeginRead :
>> ....
>> ns.BeginRead(new byte[100], 1, 0, rcvd, ns);
>>
>> as argument and used in rcvd, so you keep a reference to your
>> NetworkStream
>> (ns) the wrapped TcpClient (tp) and his underlying socket.
>> What would you expect from the GC to free here?
>>
>> Willy.
>>
>>
>>
>>
>>
>>
.
- Follow-Ups:
- Re: GC and active sockets, and Pinned Memory
- From: Arthur M.
- Re: GC and active sockets, and Pinned Memory
- References:
- GC and active sockets
- From: Arthur M.
- RE: GC and active sockets, and Pinned Memory
- From: Arthur M.
- RE: GC and active sockets, and Pinned Memory
- From: Rob White
- RE: GC and active sockets, and Pinned Memory
- From: Arthur M.
- Re: GC and active sockets, and Pinned Memory
- From: Willy Denoyette [MVP]
- Re: GC and active sockets, and Pinned Memory
- From: Arthur M.
- Re: GC and active sockets, and Pinned Memory
- From: Willy Denoyette [MVP]
- Re: GC and active sockets, and Pinned Memory
- From: Arthur M.
- GC and active sockets
- Prev by Date: PInvoke CredRead in Advapi32.dll
- Next by Date: Re: Reference Count
- Previous by thread: Re: GC and active sockets, and Pinned Memory
- Next by thread: Re: GC and active sockets, and Pinned Memory
- Index(es):
Relevant Pages
|