3

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 :)

Community
  • 1
  • 1
Harry Boy
  • 4,159
  • 17
  • 71
  • 122
  • Sorry, but this "solution" seems completely wrong to me... – Daniel Stenberg Mar 02 '15 at 07:34
  • This does not seem like a solution, to the question "How to cancel the operation immediately". I am also looking for the direct answer to this question. Kindly let me know if there is any. – Swtsvn May 04 '16 at 18:19

3 Answers3

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.

fredmaggiowski
  • 2,232
  • 3
  • 25
  • 44
santins
  • 56
  • 3
1

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

curl_easy_setopt(pEasy, CURLOPT_CONNECTTIMEOUT, 5);
Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40
  • Even that is too long for the UI responsiveness, the way the UI is designed if there were several connections then they all connect one after the other so its 5xNumConnections – Harry Boy Feb 27 '15 at 15:05
  • @HarryBoy You should not run such a blocking call under a UI thread, you will either block the UI, or use a too low timeout that will fail the operation when the network slows down/user runs on wifi/user has an intermitten network issue/etc. - both which will annoy users. Run it in another thread. – nos Mar 22 '18 at 10:13
1

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.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
  • I'm not a curl expert, but I want to throw my weight behind this solution. Socket stuff can be complicated and this gets at the heart of it. – Mark McKenna Sep 15 '20 at 13:14