Search code examples
winapiasynchronouswinhttp

Async callback call for a sync WinHTTP request


I'm using WinHTTP in sync mode, without passing the WINHTTP_FLAG_ASYNC flag, and I thought that the callback is always being called synchronously. That is indeed what's happening most of the time, but sometimes, when calling WinHttpCloseHandle, the callback isn't called with the WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING notification right away. Instead, it's being called afterwards from a different thread.

It that expected behavior? Why does it become async for some cases, if the seesion is sync? I know how to fix it (waiting for the WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING notification if I don't get it right away), but I don't understand why that's the behavior that I'm seeing.


Solution

  • WinHTTP does not promise synchronous "same thread" callbacks in synchronous mode. On the contrary, MSDN states the opposite:

    The callback function must be threadsafe and reentrant because it can be called on another thread for a separate request, and reentered on the same thread for the current request. It must therefore be coded to handle reentrance safely while processing. When the dwInternetStatus parameter is equal to WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, the callback does not need to be able to handle reentrance for the same request, because this callback is guaranteed to be the last, and does not occur when other messages for this request are handled.

    This means that the symptom you are seeing is basically behavior by design and is not related to async mode: some callback calls might be sent to you from worker threads and then thread racing might reach your code late in your callback. You need to take this into consideration and either ignore those late calls, or synchronize with them, or reset callbacks early enough explicitly to not receive late notifications.

    Regarding WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING specifically MSDN explains what you can rely on exactly (see quote above).