Windows Sockets 1.1 Blocking routines & EINPROGRESS

One major issue in porting applications from a Berkeley sockets environment to a Windows environment involves "blocking"; that is, invoking a function that does not return until the associated operation is completed. A problem arises when the operation takes an arbitrarily long time to complete: an example is a recv, which might block until data has been received from the peer system. The default behavior within the Berkeley sockets model is for a socket to operate in a blocking mode unless the programmer explicitly requests that operations be treated as nonblocking. Windows Sockets 1.1 environments could not assume pre-emptive scheduling. Therefore, it was strongly recommended that programmers use the nonblocking (asynchronous) operations if at all possible. Because this was not always possible, the psuedo-blocking facilities described below were provided.

Even on a blocking socket, some functions pics/SOCK200090000.gif bind, getsockopt, and getpeername for example pics/SOCK200090000.gif complete immediately. There is no difference between a blocking and a nonblocking operation for those functions. Other operations, such as recv, can complete immediately or could take an arbitrary time to complete, depending on various transport conditions. When applied to a blocking socket, these operations are referred to as blocking operations. All routines that can block are listed with an asterisk in the tables above and below.

With Windows Sockets 1.1, a blocking operation that cannot complete immediately is handled by psuedo-blocking as follows. The service provider initiates the operation, then enters a loop in which it dispatches any Windows messages (yielding the processor to another thread if necessary), and then checks for the completion of the Windows Sockets function. If the function has completed, or if WSACancelBlockingCall has been invoked, the blocking function completes with an appropriate result.

A service provider must allow installation of a blocking hook function that does not process messages in order to avoid the possibility of re-entrant messages while a blocking operation is outstanding. The simplest such blocking hook function would return FALSE. If a Windows Sockets DLL depends on messages for internal operation, it can execute PeekMessage(hMyWnd...) before executing the application blocking hook so that it can get its messages without affecting the rest of the system.

In a Windows Sockets 1.1 environment, if a Windows message is received for a process for which a blocking operation is in progress, there is a risk that the application will attempt to issue another Windows Sockets call. Because of the difficulty in managing this condition safely, Windows Sockets 1.1 does not support such application behavior. An application it not permitted to make more than one nested Windows Sockets function calls. Only one outstanding function call will be allowed for a particular task. The only exceptions are two functions that are provided to assist the programmer in this situation: WSAIsBlocking and WSACancelBlockingCall.

The WSAIsBlocking function can be called at any time to determine whether or not a blocking Windows Sockets 1.1 call is in progress. Similarly, the WSACancelBlockingCall fucntion can be called at any time to cancel an in-progress blocking call. Any other nesting of Windows Sockets functions will fail with the error WSAEINPROGRESS. It should be emphasized that this restriction applies to both blocking and non-blocking operations.

Although this mechanism is sufficient for simple applications, it cannot support the complex message-dispatching requirements of more advanced applications (for example, those using the MDI model). For such applications, the Windows Sockets API includes the function WSASetBlockingHook, which allows the application to specify a special routine which will be called instead of the default message dispatch routine described above.

The Windows Sockets provider calls the blocking hook only if all of the following are true: the routine is one that is defined as being able to block, the specified socket is a blocking socket, and the request cannot be completed immediately. (A socket is set to blocking by default, but the IOCTL FIONBIO or the WSAAsyncSelect function set a socket to nonblocking mode.)

The blocking hook will never be called and the application does not need to be concerned with the re-entrancy issues the blocking hook can introduce if an application follows these guideline:

  • It uses only nonblocking sockets, and;

  • It uses the WSAAsyncSelect and/or the WSAAsyncGetXByY routines instead of select and the getXbyY routines.

If a Windows Sockets 1.1 application invokes an asynchronous or nonblocking operation that takes a pointer to a memory object (a buffer, or a global variable for example) as an argument, it is the responsibility of the application to ensure that the object is available to Windows Sockets throughout the operation. The application must not invoke any Windows function that might affect the mapping or addressability of the memory involved.

Software for developers
Delphi Components
.Net Components
Software for Android Developers
More information resources
Unix Manual Pages
Delphi Examples