0

I'm using IOCP on UDP socket, and the UDP socket may be closed in another thread. So, how can I free Per Socket Context and Per I/O Context which associated with SOCKET safely?

When I close the socket, there will still be un-completed I/O request in kernel queue.

If I free context just when socket closed, the GetQueueCompletionStatus may failed.

Now, my question is when to free context?

dragonfly
  • 443
  • 2
  • 5
  • 13

4 Answers4

3

I use reference counting on all of my per socket and per I/O data structures. It makes this kind of thing easy as they are deleted when their references drop to 0. For some example code which shows one way to do this you could take a look at my free IOCP framework which you can download from here.

Len Holgate
  • 21,282
  • 4
  • 45
  • 92
1

Use a mutex to enforce mutual exclusion in a critical section of your code that will check the availability of the socket, and open it if necessary. Lock the socket to that thread, and release it appropriately when finished.

JoshJordan
  • 12,676
  • 10
  • 53
  • 63
0

I reuse my per-socket structures. After I have received completion events for all of the read and write operations that are required for that connection, I call TransmitFile with the TF_DISCONNECT and TF_REUSE_SOCKET flags to reset the socket without having to close it. I also reset the per-connection data once the completion event for the TransmitFile call comes through.

Aaron Klotz
  • 11,287
  • 1
  • 28
  • 22
0

Close the socket first. You will get error (I think it is ERROR_OPERATION_ABORTED) from GetQueuedCompletionStatus, and then it is right time to free the structure. There are no other uncompleted requests on this connection in kernel queue by then, completion packets are maintained in FIFO order, and error packet will definitely be the last one for this connection.

Vladislav Vaintroub
  • 5,308
  • 25
  • 31
  • What there are multiple packets pending? e.g. if a read and a write are pending, you don't know which one will return ERROR_OPERATION_ABORTED first, right? – Marco Pagliaricci Feb 20 '14 at 12:34
  • Ok. You still get the valid completion key and overlapped parameter returned from the GetQueuedCompletionStatus(), even with ERROR_OPERATION_ABORTED . You might use either one for the context you'll want to free. – Vladislav Vaintroub Feb 21 '14 at 20:03
  • My point is if you have *both* a write and a read (so 2 OVERLAPPED structures pending waiting for i/o completion), you don't know which of the two will be completed first, and which will be completed last (even if both returns ERROR_OPERATION_ABORTED or not), so you'll need an atomic counter to establish which will be completed *last* and then call a cleanup routine from there to dealloc memory – Marco Pagliaricci Feb 21 '14 at 21:02
  • Ok, I think I now understand what you mean. If you allocate single "connection", and use it for read and writes, and there could be multiple IOs in flight, then you'd need refcounting, and deallocate whenever your refcount goes down to 0, and you get the error. If you do not have multiple outstanding IOs, or use completely separate structures for say read and write, then you do not need refcounting. – Vladislav Vaintroub Feb 22 '14 at 00:52
  • Exactly, this is what i mean. And i mean the scenario when i allocate a per-Socket structure like struct Socket { ... SOCKET socket; }; see this discussion -> http://stackoverflow.com/questions/21907157/i-o-completion-ports-last-called-callback-or-where-its-safe-to-cleanup-thin/21928591?noredirect=1#comment33247366_21928591 – Marco Pagliaricci Feb 22 '14 at 08:08