cpprestsdk icon indicating copy to clipboard operation
cpprestsdk copied to clipboard

http request crash

Open antlafarge opened this issue 10 years ago • 10 comments

I have a crash when I try to do an http request without being connected to internet. I use the pplx with the Unreal Engine (4.9.2) and I didn't manage to reproduce that crash outside the Unreal Engine. With a new win32 console project, the exception is well catched. I activated the use of exceptions in the Unrael Engine (/EHsc).

The call stack is not very precise where the crash occurs :

Concurrency::details::_Task_impl_base::_Wait() Line 1779    C++
Concurrency::task<web::http::http_response>::get() Line 3490    C++
ApiClient::getSceneEndpoint::__l6::<lambda>(Concurrency::task<web::http::http_response> t) Line 45  C++

The last output I get :

First-chance exception at 0x000007FEFCF6965D in UE4Editor.exe: Microsoft C++ exception: web::http::http_exception at memory location 0x0000000318DFF2B0.

Here is my code :

pplx::task<SceneEndpoint> ApiClient::getSceneEndpoint(std::string accountId, std::string applicationName, std::string sceneId, std::string userData)
{

web::http::client::http_client client(std::wstring(baseUri.begin(), baseUri.end()));
web::http::http_request request(web::http::methods::POST);
std::string relativeUri = std::string("/") + accountId + "/" + applicationName + "/scenes/" + sceneId + "/token";
request.set_request_uri(std::wstring(relativeUri.begin(), relativeUri.end()));
request.headers().add(L"Content-Type", L"application/msgpack");
request.headers().add(L"Accept", L"application/json");
request.headers().add(L"x-version", L"1.0.0");
request.set_body(std::wstring(userData.begin(), userData.end()));

return client.request(request).then([](pplx::task<web::http::http_response> t) {
    try
    {
        return t.get();
    }
    catch (const std::exception& ex)
    {
        throw std::runtime_error(std::string() + "Can't reach the stormancer API server. " + ex.what());
    }
    catch (...)
    {
        throw std::runtime_error("Unknown error while reaching the stormancer API server.");
    }
}).then([](web::http::http_response response) {
    // ...
    // return the scene endpoint
}

}

You can see I try to catch everything! Any Idea?

antlafarge avatar Feb 18 '16 17:02 antlafarge

The issue is that while you do catch the exceptions thrown from .request(), you immediately rethrow. This causes another exception to propagate down the continuation chain, which in your posted source code isn't caught.

Are you using a task-based continuation on the return value of getSceneEndpoint()? What does your usage look like?

ras0219-msft avatar Feb 18 '16 19:02 ras0219-msft

Yes I catch my exception upper in my code.

pplx::task<Result<Scene*>*> Client::getPublicScene(const char* sceneId, const char* userData)
{
    if (!sceneId || !userData)
    {
            // ...
    }

    return _apiClient->getSceneEndpoint(_accountId, _applicationName, sceneId, userData).then([this, sceneId](pplx::task<SceneEndpoint> t) {
        auto result = new Result<Scene*>();
        try
        {
            SceneEndpoint sep = t.get();
            return this->getScene(sceneId, sep).then([result](pplx::task<Scene*> t) {
                try
                {
                    auto scene = t.get();
                    result->set(scene);
                }
                catch (const std::exception& ex)
                {
                    result->setError(1, ex.what());
                }
                return result;
            });
        }
        catch (const std::exception& ex)
        {
            ILogger::instance()->log(ex);
            result->setError(1, ex.what());
            return pplx::task<Result<Scene*>*>([result]() {
                return result;
            });
        }
    });
}

As you can see, I transform the exception to a Result which can have a success or fail state.

You can see I added weird or useless then and try catch for testing because I didn't manage to catch this http_exception, resulting in a crash of Unreal Engine 4.

antlafarge avatar Feb 19 '16 10:02 antlafarge

Hmm. I'm not sure then. Can you reduce this into a single-file repro and post it?

ras0219-msft avatar Feb 22 '16 16:02 ras0219-msft

I will try, but I have more informations for you now.

Le call stack:

    KernelBase.dll!000007fefcd2965d()   Unknown
    msvcr120.dll!000007fef7c81ff1() Unknown
>   myDll120_Release_x64.dll!Concurrency::details::_Task_impl_base::_Wait() Line 1779   C++
    myDll120_Release_x64.dll!ApiClient::getSceneEndpoint::__l12::<lambda>(Concurrency::task<web::http::http_response> t) Line 87    C++
    [External Code] 

And the interesting log from VS2013 / UE4 :

[2016.02.24-11.28.54:887][879]Log:Display: [2016-02-24T12:28:54Z] [5] [Client::getPublicScene] authenticator
[2016.02.24-11.28.54:890][879]Log:Display: [2016-02-24T12:28:54Z] [5] [Client::getSceneEndpoint] request [/accountId/appName/scenes/authenticator/token]
'UE4Editor.exe' (Win32): Loaded 'C:\Windows\System32\cryptsp.dll'. Cannot find or open the PDB file.
[2016.02.24-11.28.54:893][879]LogTemp: UBFGGameInstance::Init - OnlineSub
[2016.02.24-11.28.54:893][879]LogTemp: UBFGGameInstance::Init - SessionInt.IsValid(
'UE4Editor.exe' (Win32): Loaded 'C:\Windows\System32\credssp.dll'. Cannot find or open the PDB file.
'UE4Editor.exe' (Win32): Unloaded 'C:\Windows\System32\cryptsp.dll'
First-chance exception at 0x000007FEFCD2965D in UE4Editor.exe: Microsoft C++ exception: web::http::http_exception at memory location 0x00000002AB11F350.

antlafarge avatar Feb 24 '16 15:02 antlafarge

This just says an exception was thrown of type web::http::http_exception. You can potentially debug further by looking at the member _M_stackTrace of the _ExceptionHolder object.

ras0219-msft avatar Mar 31 '16 01:03 ras0219-msft

I'm having the same crash as @antlafarge. Specifically the http_client if the provided URI for the request is unreachable. Either by having no internet or by have a bogus URI.

kngako avatar Oct 23 '17 14:10 kngako

To catch the exception and avoid crash. You have to use wait(). I Fixed my code by putting wait() on the task returned by client.request() method.

lakhinsu avatar May 28 '20 09:05 lakhinsu

To catch the exception and avoid crash. You have to use wait(). I Fixed my code by putting wait() on the task returned by client.request() method.

If you use wait, you can't get the http_response. So that's not the solution.

antlafarge avatar May 28 '20 13:05 antlafarge

auto request = client.request(req); try { request.wait(); } catch (const web::http::http_exception & e) { printf("http_exception : %s", e.what()); return; }

doosupchung avatar Dec 28 '20 02:12 doosupchung

cpprest can't Crashed Issue Solution I recommend to SET - project -> Properties -> C/C++ -> Code Generation -> Runtime Library Set TO - /MD or /MDd

doosupchung avatar Apr 15 '22 01:04 doosupchung