I checked the curl_global_init/curl_global_cleanup source code to find out if I was supposed to call curl_global_cleanup after getting a non-successful return code from curl_global_init.
I expected the following
I expected to find to find an implementation that expects me to not call curl_global_cleanup after a failed init attempt, because that's the "usual way to do it" (all or nothing, you can't "release" what you didn't "acquire"). OR an implementation that expects me to call curl_global_cleanup, but at least keeps track of the initialization state, so that only the parts that were really initialized in the failed init attempt are cleaned up.
What I found
The initialized counter is immediately incremented, before any initialization is attempted. After that there are multiple error-exit points, none of which reset the initialized counter. After that the library is in a state where
It cannot be used, since it wasn't initialized completely. This is OK, after all the init function returned an error.
Calling curl_global_init again will immediately "succeed", but not change anything. This is bad, because if the library is used in a module/plugin/..., another part of the application may call curl_global_init, get the "success" return code, think all is fine and go ahead to try to use it.
Calling curl_global_cleanup will restore the initialized counter back to zero, but it may also call cleanup functions of other libraries who's corresponding init function was not even called (or at least not successfully). This again is bad in a module/plugin/..., because if the module that tried to initialize curl calls curl_global_cleanup to try to "undo" the damage to the initialized counter, curl may call the cleanup function of one of its dependencies, without having initialized it, thereby potentially undoing the initialization of this dependency that some other module may have done before.
Current master, and blame says it's been this way forever (more than 10 years).
The text was updated successfully, but these errors were encountered:
Well, the "GLOBAL CONSTANTS" section of https://curl.haxx.se/libcurl/c/libcurl.html goes into detail explaining how to initialize libcurl in an application that uses modules/plugins/... Exactly the use case described there will be problematic with the current implementation, because the second module trying to initialize libcurl will see a spurious success code.
So I guess the true reason this isn't a problem is that initialization very rarely fails (if at all), except for when it's a configuration problem (e.g. a required dependency missing on the system). And in that case (configuration problem), most computer users I know simply accept any kind of misbehavior from an application, even including crashes.
However for our use case that's not an acceptable solution.