Cancel curl_easy_perform while it is trying to connect

2

Is there a way that I can cancel a curl_easy_perform in C++??

I have a scenario where I am trying to connect to network resource that is offline and the curl_easy_perform take a certain amount of time before it returns CURLE_COULDNT_CONNECT. But in the meantime the user has closed the UI that wishes to connect and I want to immediatley cut off the curl connection and not have to wait for it to fail to connect.

I have tried storing the curl pointer that I use:

CURL *pEasy = curl_easy_init ();

And then while it is doing curl_easy_perform I called

curl_easy_cleanup(pEasy);

In an attempt to release or 'stop' the curl connection but it crashed and I got the following error from curl_easy_perform:

Unhandled exception at blah blah: Access violation reading location 0x00000004.

Is there a way I can cancel the connection attempt???? I have read this link: How can I immediately cancel a curl operation? but it seems to handle cancelling a curl connection after it has successfully connected.

EDIT - SOLUTION

I have found that if I call:

curl_easy_reset( pEasy );

Then

curlResult = curl_easy_perform ( pEasy );

returns almost immediately with the result CURLE_OPERATION_TIMEDOUT.

I think this is what I need :)

c++
c
curl
libcurl
asked on Stack Overflow Feb 27, 2015 by Harry Boy • edited May 23, 2017 by Community

3 Answers

2

You can run curl_easy_perform in a thread and keep the CURL object.

On the CURL object call curl_easy_setopt(m_chatCurl, CURLOPT_TIMEOUT_MS, 1) whenever you want to close the connection.

This way the connection will timeout and the thread will be able to finish.

answered on Stack Overflow Apr 15, 2016 by user2751694 • edited Apr 15, 2016 by FredMaggiowski
1

Rather than cancelling the attempt, you can set a connection timeout beforehand, eg. :

curl_easy_setopt(pEasy, CURLOPT_CONNECTTIMEOUT, 5);
answered on Stack Overflow Feb 27, 2015 by Sander De Dycker
0

While changing the timeout option is probably fine, as it probably is just forwarded to the socket itself, I think that it's better to simply close the socket.

void terminateConnectionNow(CURL* curlHandle)
{
    curl_socket_t sockfd;
    auto res = curl_easy_getinfo(curlHandle, CURLINFO_ACTIVESOCKET, &sockfd);
    // ASSERT_EQ(res, CURLE_OK); - no point in doing anything if the socket is not there
    closesocket(sockfd);
}

Closing the socket ensures total break of the connection, regardless of whever it's connecting, sending, receiveing, etc, so no chance of it getting connected in the very last moment.

Contrary to curl_easy_cleanup, curl will not crash even if that operation is performed from another thread - sockets themselves are managed by the OS, so closing the socket is thread safe. Then, curl is properly defended against errors coming from socket operations. When socket is manually closed, operations like curl_easy_recv will just return error codes, for example: CURLE_RECV_ERROR.

While accessing the curl-options and reading the socket handle may look like a risky operation, so is setting the timeout. However, when reading the socket handle, the curl state is not modified, only the cached socket is read, so I see it as even safer option.

For total safety, you can obtain the socket with a callback and store it aside, so you can access it from another thread without touching curl handle at all. You can see this approach here.

Of course, closing the socket does not mean the curl handle is closed. The curl handle is still alive, you still need to make sure that handle is destroyed with curl_easy_cleanup - but not before you ensure that all threads fail their connect/send/recv operations and leave the curl handle alone, or otherwise you risk that access-violation.

answered on Stack Overflow Jul 6, 2019 by quetzalcoatl

User contributions licensed under CC BY-SA 3.0