3

I have an asynchronous socket server. I have encountered a issue where problematic clients and hard to reproduce network events cause an insane number of byte[]'s to get pinned. Since all the threading to handle clients is implicit (I use BeginAcceptClient, and I use callbacks instead of threads that are explicitly instantiated) I don't control the pinning process. By "implicit threading" I mean threads generated not by me directly, but by the runtime hosting my application.

At any rate the answer in this post shows how to unpin objects. Is it possible to override the behind the scenes pinning if I go on ahead and pin my byte[]'s myself, do the BeginRead and unpin during cleanup?

Thanks.

Community
  • 1
  • 1
kmarks2
  • 4,755
  • 10
  • 48
  • 77

2 Answers2

4

The answer in the post you linked to is completely wrong (I just left a comment there). Only when the last pinning handle (more general: pinning "reason" because there are other reasons than GCHandles) is removed the object is unpinned. You cannot force unpinning. That would be terribly unsafe. You could use safe managed code to do unsafe things which is even a security problem!

Anyway, it does not make sense for you to try to prevent pinning of the object. Even if this was possible, which it is not, your process would crash at random times! Socket relies on pinning for correctness. It does not do this without reason.

The solution is elsewhere:

  1. Create all buffers at application startup so all buffers are contiguous in memory. Use a buffer pool.
  2. Use a small number of large buffers and assign sections of it to individual clients.

A small side note: Pinning is implemented differently from what you think. Pinning is not a flag you can turn on and off on an object. When you pin something, nothing special happens at first. Only when the GC runs, the GC notices that there are references with the special property that they are pinning. It then prevents the object from being moved.

usr
  • 168,620
  • 35
  • 240
  • 369
1

I would suggest that you instead of focusing on Pin/Unpin do all of your socket calls from a different AppDomain. You could then, when you are at an 'idle/safe' point, unload and reload that AppDomain to reset the memory in it to a good state.

GWLlosa
  • 23,995
  • 17
  • 79
  • 116
  • 1
    He could just do a manual GC which would clear out all unused buffers as well. Shutting down an appdomain does not add any new capability regarding GC. The GC is process-global. – usr May 21 '12 at 20:59
  • 1
    The GC is process-global, but clearing out the AppDomain will call all the finalizers on the items in that domain; one of which, hopefully, may call Free on the GCHandle that is still holding the buffer. It depends on the code in question, but it may free up the array for the GC to collect on its next sweep. – GWLlosa May 21 '12 at 21:05
  • 1
    You are assuming there are handle-leaks. The BCL Socket implementation surely does not have any, and he is not doing any pinning himself. Anyway, shutting down the appdomain disconnects the socket. – usr May 21 '12 at 21:08
  • I agree; shutting down the appDomain will disconnect the socket. But someone must be leaking something; since unpinning memory someone else has pinned is difficult/error prone, the closest I think you can get is to clear out the AppDomain to hope that someone else is in a better position to clean up the buffers. This is assuming the buffers are not under your control. – GWLlosa May 21 '12 at 21:22