Graceful Shutdown, Linger Options, and Socket Closure

The following material is provided as clarification for the subject of shutting down socket connections closing the sockets. It is important to distinguish the difference between shutting down a socket connection and closing a socket.

Shutting down a socket connection involves an exchange of protocol messages between the two endpoints, hereafter referred to as a shutdown sequence. Two general classes of shutdown sequences are defined: graceful and abortive (also called hard). In a graceful shutdown sequence, any data that has been queued, but not yet transmitted can be sent prior to the connection being closed. In an abortive shutdown, any unsent data is lost. The occurrence of a shutdown sequence (graceful or abortive) can also be used to provide an FD_CLOSE indication to the associated applications signifying that a shutdown is in progress.

Closing a socket, on the other hand, causes the socket handle to become deallocated so that the application can no longer reference or use the socket in any manner.

In Windows Sockets, both the shutdown function, and the WSASendDisconnect function can be used to initiate a shutdown sequence, while the closesocket function is used to deallocate socket handles and free up any associated resources. Some amount of confusion arises, however, from the fact that the closesocket function implicitly causes a shutdown sequence to occur if it has not already happened. In fact, it has become a rather common programming practice to rely on this feature and to use closesocket to both initiate the shutdown sequence and deallocate the socket handle.

To facilitate this usage, the sockets interface provides for controls by way of the socket option mechanism that allow the programmer to indicate whether the implicit shutdown sequence should be graceful or abortive, and also whether the closesocket function should linger (that is not complete immediately) to allow time for a graceful shutdown sequence to complete. These important distinctions and the ramifications of using closesocket in this manner are still not widely understood.

By establishing appropriate values for the socket options SO_LINGER and SO_DONTLINGER, the following types of behavior can be obtained with the closesocket function:

  • Abortive shutdown sequence, immediate return from closesocket.
  • Graceful shutdown, delaying return until either shutdown sequence completes or a specified time interval elapses. If the time interval expires before the graceful shutdown sequence completes, an abortive shutdown sequence occurs, and closesocket returns.
  • Graceful shutdown, immediate return—allowing the shutdown sequence to complete in the background. Although this is the default behavior, the application has no way of knowing when (or whether) the graceful shutdown sequence actually completes.

The use of the SO_LINGER and SO_DONTLINGER socket options and the associated linger structure is discussed in more detail in the reference sections on SOL_SOCKET Socket Options and the linger structure.

One technique that can be used to minimize the chance of problems occurring during connection teardown is to avoid relying on an implicit shutdown being initiated by closesocket. Instead, use one of the two explicit shutdown functions, shutdown or WSASendDisconnect. This in turn causes an FD_CLOSE indication to be received by the peer application indicating that all pending data has been received. To illustrate this, the following table shows the functions that would be invoked by the client and server components of an application, where the client is responsible for initiating a graceful shutdown.

Client sideServer side
(1) Invokes shutdown(s, SD_SEND) to signal end of session and that client has no more data to send.
(2) Receives FD_CLOSE, indicating graceful shutdown in progress and that all data has been received.
(3) Sends any remaining response data.
(local timing significance only) Gets FD_READ and calls recv to get any response data sent by server .(4) Invokes shutdown(s, SD_SEND) to indicate server has no more data to send.
(5) Receives FD_CLOSE indication.(local timing significance only) Invokes closesocket .
(6) Invokes closesocket.

 

Send comments about this topic to Microsoft

Build date: 11/12/2009

Tags :


Community Content

Calmarius
recv returns 0 when graceful shotdown initiated
recv can also indicates that graceful shutdown process initiated by returning 0.
Tags :

Paul Sheer
closesocket() with linger broken for graceful shutdown - workaround

Anyone who wants to do a graceful shutdown (with IOCP in my case) should
look at bug 4468997 on the Sun Developers Network.

Windows closesocket() is completely broken and actually doesn't work properly.
The SO_LINGER and SO_DONTLINGER options also do not work.

See:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4468997

What DOES work is it do a

DisconnectEx(sock, NULL, 0, 0);
closesocket(sock)

and this is the only way to get a proper shutdown without clipping trailing
bytes from the stream you have just written.

That is, EVEN IF your WSASend(sock, &d, 1, &l, 0, &iocp, NULL); has posted 'iocp'
as SUCCESSFULLY completed, it STILL does not mean you can safely do a closesocket().

A successfully completed IOCP for WSASend just means that the data has been
queued. That same data will be DROPPED if closesocket() is called.

What I am saying here is quite frightening: the only safe way to close a
socket is to use an undocumented ... er ... side-effect. The link above shows
that the Java virtual machine has (had) the same problem, and the same
workaround.

This whole page should be replaced with the following:

---

To abort a connection, release a socket handle, and discard data pending for writing, do:

closesocket(sock);
sock = INVALID_SOCKET; // do not make further use of sock.

To flush a sock handle, gracefully close the socket, and release the socket handle in the
background:

DisconnectEx(sock, NULL, 0, 0); // retrieve this function pointer with WSAIoctl(WSAID_DISCONNECTEX).
closesocket(sock);
sock = INVALID_SOCKET; // do not make further use of sock.

Do not use the SO_DONTLINGER or SO_LINGER options.

---


Tags : contentbug

Page view tracker