summaryrefslogtreecommitdiff
path: root/ucb
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2021-10-26 13:52:29 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2021-11-01 19:01:33 +0100
commit5d845fd02700c43352740cc9e675c91a6876e7d9 (patch)
tree777692be01fc525a6ac212776b46ec9a5bf8df43 /ucb
parenteb7fecd8ef3c0507ac6f9f60cc25161d84349e93 (diff)
ucb: webdav-curl: implement CurlSession::abort()
It looks like libcurl has an API to wake up a transfer in another thread, but have to use curl_multi_poll() instead of curl_multi_wait() to enable that. Change-Id: I728416eba45eb6665b0041955cdce8bee07e845e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124220 Tested-by: Michael Stahl <michael.stahl@allotropia.de> Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'ucb')
-rw-r--r--ucb/source/ucp/webdav-curl/CurlSession.cxx25
-rw-r--r--ucb/source/ucp/webdav-curl/CurlSession.hxx3
-rw-r--r--ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx14
-rw-r--r--ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx2
-rw-r--r--ucb/source/ucp/webdav-curl/webdavcontent.cxx2
5 files changed, 34 insertions, 12 deletions
diff --git a/ucb/source/ucp/webdav-curl/CurlSession.cxx b/ucb/source/ucp/webdav-curl/CurlSession.cxx
index 76fdbce1bac5..6fb54998c531 100644
--- a/ucb/source/ucp/webdav-curl/CurlSession.cxx
+++ b/ucb/source/ucp/webdav-curl/CurlSession.cxx
@@ -589,11 +589,16 @@ auto CurlSession::UsesProxy() -> bool
auto CurlSession::abort() -> void
{
- // this is using synchronous libcurl apis - no way to abort?
- // might be possible with more complexity and CURLOPT_CONNECT_ONLY
- // or curl_multi API, but is it worth the complexity?
- // ... it looks like CURLOPT_CONNECT_ONLY would disable all HTTP handling.
- // abort() was a no-op since OOo 3.2 and before that it crashed.
+ // note: abort() was a no-op since OOo 3.2 and before that it crashed.
+ bool expected(false);
+ // it would be pointless to lock m_Mutex here as the other thread holds it
+ if (m_AbortFlag.compare_exchange_strong(expected, true))
+ {
+ // This function looks safe to call without m_Mutex as long as the
+ // m_pCurlMulti handle is not destroyed, and the caller must own a ref
+ // to this object which keeps it alive; it should cause poll to return.
+ curl_multi_wakeup(m_pCurlMulti.get());
+ }
}
/// this is just a bunch of static member functions called from CurlSession
@@ -663,6 +668,10 @@ auto CurlProcessor::ProcessRequestImpl(
::std::pair<::std::vector<OUString> const&, DAVResource&> const* const pRequestedHeaders)
-> void
{
+ // Clear flag before transfer starts; only a transfer started before
+ // calling abort() will be aborted, not one started later.
+ rSession.m_AbortFlag.store(false);
+
if (pEnv)
{ // add custom request headers passed by caller
for (auto const& rHeader : pEnv->m_aRequestHeaders)
@@ -887,7 +896,7 @@ auto CurlProcessor::ProcessRequestImpl(
break;
}
int nFDs;
- mc = curl_multi_wait(rSession.m_pCurlMulti.get(), nullptr, 0, rSession.m_nReadTimeout,
+ mc = curl_multi_poll(rSession.m_pCurlMulti.get(), nullptr, 0, rSession.m_nReadTimeout,
&nFDs);
if (mc != CURLM_OK)
{
@@ -897,6 +906,10 @@ auto CurlProcessor::ProcessRequestImpl(
DAVException::DAV_HTTP_CONNECT,
ConnectionEndPointString(rSession.m_URI.GetHost(), rSession.m_URI.GetPort()));
}
+ if (rSession.m_AbortFlag.load())
+ { // flag was set by abort() -> not sure what exception to throw?
+ throw DAVException(DAVException::DAV_HTTP_ERROR, "abort() was called", 0);
+ }
} while (nRunning != 0);
// there should be exactly 1 CURLMsg now, but the interface is
// extensible so future libcurl versions could yield additional things
diff --git a/ucb/source/ucp/webdav-curl/CurlSession.hxx b/ucb/source/ucp/webdav-curl/CurlSession.hxx
index 67e4e3616aab..73b32096f6ea 100644
--- a/ucb/source/ucp/webdav-curl/CurlSession.hxx
+++ b/ucb/source/ucp/webdav-curl/CurlSession.hxx
@@ -14,6 +14,7 @@
#include <curl/curl.h>
+#include <atomic>
#include <mutex>
namespace http_dav_ucp
@@ -37,6 +38,8 @@ private:
bool m_isAuthenticatedProxy = false;
/// read timeout in milliseconds (connection timeout is stored in m_pCurl)
int m_nReadTimeout = 0;
+ /// flag to signal abort to transferring thread
+ ::std::atomic<bool> m_AbortFlag;
/// libcurl multi handle
::std::unique_ptr<CURLM, deleter_from_fn<curl_multi_cleanup>> m_pCurlMulti;
diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
index a6bfd7d79642..248d65b8c60c 100644
--- a/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
+++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx
@@ -570,10 +570,16 @@ void DAVResourceAccess::GET(
void DAVResourceAccess::abort()
{
- // 17.11.09 (tkr): abort currently disabled caused by issue i106766
- // initialize();
- // m_xSession->abort();
- SAL_INFO("ucb.ucp.webdav", "Not implemented. -> #i106766#" );
+ // seems pointless to call initialize() here, but prepare for nullptr
+ decltype(m_xSession) xSession;
+ {
+ osl::Guard<osl::Mutex> const g(m_aMutex);
+ xSession = m_xSession;
+ }
+ if (xSession.is())
+ {
+ xSession->abort();
+ }
}
diff --git a/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
index 1abde0fe2d8e..df27713a936d 100644
--- a/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
+++ b/ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx
@@ -194,7 +194,7 @@ public:
/// @throws DAVException
void
- static abort();
+ abort();
// helper
static void
diff --git a/ucb/source/ucp/webdav-curl/webdavcontent.cxx b/ucb/source/ucp/webdav-curl/webdavcontent.cxx
index dc9b373ed5b1..a49969f3902f 100644
--- a/ucb/source/ucp/webdav-curl/webdavcontent.cxx
+++ b/ucb/source/ucp/webdav-curl/webdavcontent.cxx
@@ -781,7 +781,7 @@ void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
osl::MutexGuard aGuard( m_aMutex );
xResAccess.reset( new DAVResourceAccess( *m_xResAccess ) );
}
- DAVResourceAccess::abort();
+ xResAccess->abort();
{
osl::Guard< osl::Mutex > aGuard( m_aMutex );
m_xResAccess.reset( new DAVResourceAccess( *xResAccess ) );