Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

caveat : global initialization of libcurl #4

Closed
embeddedmz opened this issue Mar 28, 2019 · 2 comments
Closed

caveat : global initialization of libcurl #4

embeddedmz opened this issue Mar 28, 2019 · 2 comments
Labels

Comments

@embeddedmz
Copy link
Owner

libcurl global initialization is currently handled in the constructor with a static mutex and a counter of CFTPClient objects :

   s_mtxCurlSession.lock();
   if (s_iCurlSession++ == 0)
   {
      curl_global_init(CURL_GLOBAL_ALL);
   }
   s_mtxCurlSession.unlock();

ditto for the global cleanup in destructor :

   s_mtxCurlSession.lock();
   if (--s_iCurlSession <= 0)
   {
      curl_global_cleanup();
   }
   s_mtxCurlSession.unlock();

If in your application, there's only ftpclient-cpp using libcurl, there's no issues.

However, if you use it with another 3rd party library (e.g. httpclient-cpp) that initializes curl in a thread different from any other thread where CFTPClient objects live, there will be undefined behavior (crashs, bugs, dragons, clowns etc...). As stated here : https://curl.haxx.se/libcurl/c/curl_global_init.html curl_global_init isn't thread safe.

I think it's better to remove this stupid "hack" and explicitly call curl_global_init(CURL_GLOBAL_ALL); at the beginning of your program and call curl_global_cleanup(); at the end of it. Adding a static method is a good way to achieve that.

@Finkman
Copy link
Contributor

Finkman commented Mar 30, 2020

The issue seems to come from libraries that are used by libcurl which puts libcurl in the same topic as we are discussing.

Even putting curl_global_init(CURL_GLOBAL_ALL); in a static method like init_globals() might be wrong, since it prevents the caller to set the different options of CURL_GLOBAL_XX which are required in some scenarios.

IMHO, the best option would be a c++ wrapper for curl which does that work and provides those options in it's own scope. All c-like functions could be made in oop-style and your library would be a consumer of that curl-cpp library, so no worries.

A compromise to that, since there is actually no wrapper, would be to make a c++ lib handle like proposed in #7. It could be used in the application and should be needed in the ftpclient ctor to enforce the creation of the handle.

int main(){
  auto client FTPClient{CurlHandle{}, [](auto const& logMsg){}};
}

Beside the handle idea, I'm going to investigate into the idea of a curl-cpp library, maybe it could be useful anyway.

@embeddedmz
Copy link
Owner Author

embeddedmz commented Apr 26, 2021

Finkman solution (a static constructor similar to the one that can be made in C# or Java) fixes the issue. I will use the same pattern in the httpclient-cpp and mailclient-cpp projects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants