diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2021-10-26 13:52:29 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2021-11-01 19:01:33 +0100 |
commit | 5d845fd02700c43352740cc9e675c91a6876e7d9 (patch) | |
tree | 777692be01fc525a6ac212776b46ec9a5bf8df43 /ucb/source | |
parent | eb7fecd8ef3c0507ac6f9f60cc25161d84349e93 (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/source')
-rw-r--r-- | ucb/source/ucp/webdav-curl/CurlSession.cxx | 25 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/CurlSession.hxx | 3 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/DAVResourceAccess.cxx | 14 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/DAVResourceAccess.hxx | 2 | ||||
-rw-r--r-- | ucb/source/ucp/webdav-curl/webdavcontent.cxx | 2 |
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 ) ); |