mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2025-01-03 13:07:24 +00:00
Wrap CURL* in a std::unique_ptr (#2495)
This is safer and clarifies the ownership of pointers. Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
This commit is contained in:
parent
60b871e0ae
commit
77ffe7d634
31
src/curl.cpp
31
src/curl.cpp
@ -79,6 +79,16 @@ static constexpr char SPECIAL_DARWIN_MIME_FILE[] = "/etc/apache2/mime.typ
|
||||
#define S3FS_CURLOPT_XFERINFOFUNCTION CURLOPT_PROGRESSFUNCTION
|
||||
#endif
|
||||
|
||||
// Wrappers to pass std::unique_ptr to raw pointer functions. Undefine curl_easy_setopt to work around curl variadic argument macro.
|
||||
#undef curl_easy_setopt
|
||||
template<typename Arg> CURLcode curl_easy_setopt(const CurlUniquePtr& handle, CURLoption option, Arg arg) {
|
||||
return curl_easy_setopt(handle.get(), option, arg);
|
||||
}
|
||||
|
||||
template<typename Arg> CURLcode curl_easy_getinfo(const CurlUniquePtr& handle, CURLINFO info, Arg arg) {
|
||||
return curl_easy_getinfo(handle.get(), info, arg);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Class S3fsCurl
|
||||
//-------------------------------------------------------------------
|
||||
@ -1842,7 +1852,7 @@ bool S3fsCurl::PreHeadRequestSetCurlOpts(S3fsCurl* s3fscurl)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCurl::AddUserAgent(CURL* hCurl)
|
||||
bool S3fsCurl::AddUserAgent(const CurlUniquePtr& hCurl)
|
||||
{
|
||||
if(!hCurl){
|
||||
return false;
|
||||
@ -1939,7 +1949,7 @@ int S3fsCurl::RawCurlDebugFunc(const CURL* hcurl, curl_infotype type, char* data
|
||||
// Methods for S3fsCurl
|
||||
//-------------------------------------------------------------------
|
||||
S3fsCurl::S3fsCurl(bool ahbe) :
|
||||
hCurl(nullptr), type(REQTYPE::UNSET), requestHeaders(nullptr),
|
||||
type(REQTYPE::UNSET), requestHeaders(nullptr),
|
||||
LastResponseCode(S3FSCURL_RESPONSECODE_NOTSET), postdata(nullptr), postdata_remaining(0), is_use_ahbe(ahbe),
|
||||
retry_count(0), b_infile(nullptr), b_postdata(nullptr), b_postdata_remaining(0), b_partdata_startpos(0), b_partdata_size(0),
|
||||
b_ssekey_pos(-1), b_ssetype(sse_type_t::SSE_DISABLE),
|
||||
@ -1965,7 +1975,7 @@ bool S3fsCurl::ResetHandle()
|
||||
curl_warnings_once = true;
|
||||
}
|
||||
|
||||
sCurlPool->ResetHandler(hCurl);
|
||||
sCurlPool->ResetHandler(hCurl.get());
|
||||
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_NOSIGNAL, 1)){
|
||||
return false;
|
||||
@ -1982,7 +1992,7 @@ bool S3fsCurl::ResetHandle()
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, S3FS_CURLOPT_XFERINFOFUNCTION, S3fsCurl::CurlProgress)){
|
||||
return false;
|
||||
}
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_PROGRESSDATA, hCurl)){
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_PROGRESSDATA, hCurl.get())){
|
||||
return false;
|
||||
}
|
||||
// curl_easy_setopt(hCurl, CURLOPT_FORBID_REUSE, 1);
|
||||
@ -2083,7 +2093,7 @@ bool S3fsCurl::ResetHandle()
|
||||
}
|
||||
}
|
||||
|
||||
S3fsCurl::curl_progress[hCurl] = {time(nullptr), -1, -1};
|
||||
S3fsCurl::curl_progress[hCurl.get()] = {time(nullptr), -1, -1};
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2140,9 +2150,8 @@ bool S3fsCurl::DestroyCurlHandleHasLock(bool restore_pool, bool clear_internal_d
|
||||
}
|
||||
|
||||
if(hCurl){
|
||||
S3fsCurl::curl_progress.erase(hCurl);
|
||||
sCurlPool->ReturnHandler(hCurl, restore_pool);
|
||||
hCurl = nullptr;
|
||||
S3fsCurl::curl_progress.erase(hCurl.get());
|
||||
sCurlPool->ReturnHandler(std::move(hCurl), restore_pool);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
@ -2540,7 +2549,7 @@ int S3fsCurl::RequestPerform(bool dontAddAuthHeaders /*=false*/)
|
||||
{
|
||||
if(S3fsLog::IsS3fsLogDbg()){
|
||||
char* ptr_url = nullptr;
|
||||
curl_easy_getinfo(hCurl, CURLINFO_EFFECTIVE_URL , &ptr_url);
|
||||
curl_easy_getinfo(hCurl, CURLINFO_EFFECTIVE_URL, &ptr_url);
|
||||
S3FS_PRN_DBG("connecting to URL %s", SAFESTRPTR(ptr_url));
|
||||
}
|
||||
|
||||
@ -2563,7 +2572,7 @@ int S3fsCurl::RequestPerform(bool dontAddAuthHeaders /*=false*/)
|
||||
}
|
||||
|
||||
// Requests
|
||||
curlCode = curl_easy_perform(hCurl);
|
||||
curlCode = curl_easy_perform(hCurl.get());
|
||||
|
||||
// Check result
|
||||
switch(curlCode){
|
||||
@ -2691,7 +2700,7 @@ int S3fsCurl::RequestPerform(bool dontAddAuthHeaders /*=false*/)
|
||||
sleep(4);
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(S3fsCurl::curl_handles_lock);
|
||||
S3fsCurl::curl_progress[hCurl] = {time(nullptr), -1, -1};
|
||||
S3fsCurl::curl_progress[hCurl.get()] = {time(nullptr), -1, -1};
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -76,6 +76,7 @@ struct curlprogress {
|
||||
double dl_progress;
|
||||
double ul_progress;
|
||||
};
|
||||
typedef std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> CurlUniquePtr;
|
||||
|
||||
//----------------------------------------------
|
||||
// class S3fsCurl
|
||||
@ -173,7 +174,7 @@ class S3fsCurl
|
||||
static long ipresolve_type; // this value is a libcurl symbol.
|
||||
|
||||
// variables
|
||||
CURL* hCurl;
|
||||
CurlUniquePtr hCurl = {nullptr, curl_easy_cleanup};
|
||||
REQTYPE type; // type of request
|
||||
std::string path; // target object path
|
||||
std::string base_path; // base path (for multi curl head request)
|
||||
@ -256,7 +257,7 @@ class S3fsCurl
|
||||
static bool LoadEnvSseCKeys();
|
||||
static bool LoadEnvSseKmsid();
|
||||
static bool PushbackSseKeys(const std::string& onekey);
|
||||
static bool AddUserAgent(CURL* hCurl);
|
||||
static bool AddUserAgent(const CurlUniquePtr& hCurl);
|
||||
|
||||
static int CurlDebugFunc(const CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr);
|
||||
static int CurlDebugBodyInFunc(const CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr);
|
||||
@ -391,7 +392,6 @@ class S3fsCurl
|
||||
int MultipartRenameRequest(const char* from, const char* to, headers_t& meta, off_t size);
|
||||
|
||||
// methods(variables)
|
||||
CURL* GetCurlHandle() const { return hCurl; }
|
||||
const std::string& GetPath() const { return path; }
|
||||
const std::string& GetBasePath() const { return base_path; }
|
||||
const std::string& GetSpecialSavedPath() const { return saved_path; }
|
||||
|
@ -29,13 +29,13 @@
|
||||
bool CurlHandlerPool::Init()
|
||||
{
|
||||
for(int cnt = 0; cnt < mMaxHandlers; ++cnt){
|
||||
CURL* hCurl = curl_easy_init();
|
||||
CurlUniquePtr hCurl(curl_easy_init(), &curl_easy_cleanup);
|
||||
if(!hCurl){
|
||||
S3FS_PRN_ERR("Init curl handlers pool failed");
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
mPool.push_back(hCurl);
|
||||
mPool.push_back(std::move(hCurl));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -45,23 +45,19 @@ bool CurlHandlerPool::Destroy()
|
||||
const std::lock_guard<std::mutex> lock(mLock);
|
||||
|
||||
while(!mPool.empty()){
|
||||
CURL* hCurl = mPool.back();
|
||||
mPool.pop_back();
|
||||
if(hCurl){
|
||||
curl_easy_cleanup(hCurl);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CURL* CurlHandlerPool::GetHandler(bool only_pool)
|
||||
CurlUniquePtr CurlHandlerPool::GetHandler(bool only_pool)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(mLock);
|
||||
|
||||
CURL* hCurl = nullptr;
|
||||
CurlUniquePtr hCurl(nullptr, curl_easy_cleanup);
|
||||
|
||||
if(!mPool.empty()){
|
||||
hCurl = mPool.back();
|
||||
hCurl = std::move(mPool.back());
|
||||
mPool.pop_back();
|
||||
S3FS_PRN_DBG("Get handler from pool: rest = %d", static_cast<int>(mPool.size()));
|
||||
}
|
||||
@ -70,12 +66,12 @@ CURL* CurlHandlerPool::GetHandler(bool only_pool)
|
||||
}
|
||||
if(!hCurl){
|
||||
S3FS_PRN_INFO("Pool empty: force to create new handler");
|
||||
hCurl = curl_easy_init();
|
||||
hCurl.reset(curl_easy_init());
|
||||
}
|
||||
return hCurl;
|
||||
}
|
||||
|
||||
void CurlHandlerPool::ReturnHandler(CURL* hCurl, bool restore_pool)
|
||||
void CurlHandlerPool::ReturnHandler(CurlUniquePtr&& hCurl, bool restore_pool)
|
||||
{
|
||||
if(!hCurl){
|
||||
return;
|
||||
@ -84,19 +80,14 @@ void CurlHandlerPool::ReturnHandler(CURL* hCurl, bool restore_pool)
|
||||
|
||||
if(restore_pool){
|
||||
S3FS_PRN_DBG("Return handler to pool");
|
||||
mPool.push_back(hCurl);
|
||||
mPool.push_back(std::move(hCurl));
|
||||
|
||||
while(mMaxHandlers < static_cast<int>(mPool.size())){
|
||||
CURL* hOldCurl = mPool.front();
|
||||
mPool.pop_front();
|
||||
if(hOldCurl){
|
||||
S3FS_PRN_INFO("Pool full: destroy the oldest handler");
|
||||
curl_easy_cleanup(hOldCurl);
|
||||
}
|
||||
mPool.pop_front();
|
||||
}
|
||||
}else{
|
||||
S3FS_PRN_INFO("Pool full: destroy the handler");
|
||||
curl_easy_cleanup(hCurl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,13 @@
|
||||
#include <cassert>
|
||||
#include <curl/curl.h>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
//----------------------------------------------
|
||||
// Typedefs
|
||||
//----------------------------------------------
|
||||
typedef std::list<CURL*> hcurllist_t;
|
||||
typedef std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> CurlUniquePtr;
|
||||
|
||||
//----------------------------------------------
|
||||
// class CurlHandlerPool
|
||||
@ -49,14 +50,14 @@ class CurlHandlerPool
|
||||
bool Init();
|
||||
bool Destroy();
|
||||
|
||||
CURL* GetHandler(bool only_pool);
|
||||
void ReturnHandler(CURL* hCurl, bool restore_pool);
|
||||
CurlUniquePtr GetHandler(bool only_pool);
|
||||
void ReturnHandler(CurlUniquePtr&& hCurl, bool restore_pool);
|
||||
void ResetHandler(CURL* hCurl);
|
||||
|
||||
private:
|
||||
int mMaxHandlers;
|
||||
std::mutex mLock;
|
||||
hcurllist_t mPool;
|
||||
std::list<CurlUniquePtr> mPool;
|
||||
};
|
||||
|
||||
#endif // S3FS_CURL_HANDLERPOOL_H_
|
||||
|
Loading…
Reference in New Issue
Block a user