The current blocking version of HCCleanup has 3 major flaws:

- It always uses the system task queue, which may be undesirable by some clients
- It blocks waiting for the internal work to complete, which could cause a deadlock
- It does not expose a result so in the case of multiple libHttpClient initializations it is impossible to tell if the memory hooks are safe to remove

This change simply exposes the internal asynchronous cleanup functionality allowing the caller control to bypass all these issues
This commit is contained in:
Luca Beltrami 2020-09-25 12:55:27 -07:00 коммит произвёл GitHub
Родитель 0541869696
Коммит 1eb312c47f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 56 добавлений и 6 удалений

Просмотреть файл

@ -136,9 +136,19 @@ STDAPI HCInitialize(_In_opt_ HCInitArgs* args) noexcept;
/// Immediately reclaims all resources associated with the library.
/// If you called HCMemSetFunctions(), call this before shutting down your app's memory manager.
/// </summary>
/// <remarks>
/// Deprecated, Use HCCleanupAsync instead which allows control of which queue is running the cleanup work and does not potentially deadlock.
/// </remarks>
/// <returns></returns>
STDAPI_(void) HCCleanup() noexcept;
/// <summary>
/// Reclaims all resources associated with the library.
/// If you called HCMemSetFunctions(), call this before shutting down your app's memory manager.
/// </summary>
/// <returns></returns>
STDAPI HCCleanupAsync(XAsyncBlock* async) noexcept;
/// <summary>
/// Returns the version of the library
/// </summary>

Просмотреть файл

@ -5,6 +5,7 @@
#include "../HTTP/httpcall.h"
#include "buildver.h"
#include "global.h"
#include "../Logger/trace_internal.h"
#include "../Mock/lhc_mock.h"
#if !HC_NOWEBSOCKETS
@ -33,6 +34,8 @@ HRESULT http_singleton::singleton_access(
// Create the singleton only for the first client calling create
if (!s_useCount)
{
HCTraceImplInit();
PerformEnv performEnv;
RETURN_IF_FAILED(Internal_InitializeHttpPlatform(createArgs, performEnv));
@ -113,7 +116,38 @@ HRESULT http_singleton::cleanup_async(
) noexcept
{
std::shared_ptr<http_singleton> singleton{};
RETURN_IF_FAILED(singleton_access(singleton_access_mode::cleanup, nullptr, singleton));
HRESULT hr = singleton_access(singleton_access_mode::cleanup, nullptr, singleton);
// if the singleton is still in use, or already cleaned up, fail immediately
if (FAILED(hr))
{
intptr_t hrPtrSize = hr;
return XAsyncBegin(
async,
reinterpret_cast<void*>(hrPtrSize),
reinterpret_cast<void*>(cleanup_async),
__FUNCTION__,
[](XAsyncOp op, const XAsyncProviderData* data)
{
switch (op)
{
case XAsyncOp::Begin:
{
intptr_t hrPtrSize = reinterpret_cast<intptr_t>(data->context);
return static_cast<HRESULT>(hrPtrSize);
}
case XAsyncOp::Cleanup:
{
return S_OK;
}
default:
{
assert(false);
return S_OK;
}
}
});
}
return XAsyncBegin(
async,
@ -147,6 +181,9 @@ HRESULT http_singleton::cleanup_async(
// self is the only reference at this point, the singleton will be destroyed on this thread.
self.reset();
// cleanup tracing now that we are done
HCTraceImplCleanup();
XAsyncComplete(data->async, S_OK, 0);
return S_OK;
}

Просмотреть файл

@ -5,7 +5,6 @@
#include "../HTTP/httpcall.h"
#include "buildver.h"
#include "global.h"
#include "../Logger/trace_internal.h"
using namespace xbox::httpclient;
@ -27,7 +26,6 @@ STDAPI
HCInitialize(_In_opt_ HCInitArgs* args) noexcept
try
{
HCTraceImplInit();
return http_singleton::create(args);
}
CATCH_RETURN()
@ -36,16 +34,21 @@ STDAPI_(void) HCCleanup() noexcept
try
{
XAsyncBlock async{};
HRESULT hr = http_singleton::cleanup_async(&async);
HRESULT hr = HCCleanupAsync(&async);
if (SUCCEEDED(hr))
{
XAsyncGetStatus(&async, true);
}
HCTraceImplCleanup();
}
CATCH_RETURN_WITH(;)
STDAPI HCCleanupAsync(XAsyncBlock* async) noexcept
try
{
return http_singleton::cleanup_async(async);
}
CATCH_RETURN()
STDAPI
HCSetGlobalProxy(_In_ const char* proxyUri) noexcept
try