diff --git a/src/hg_connect_http.rs b/src/hg_connect_http.rs index c0339d20f..08e6d79f4 100644 --- a/src/hg_connect_http.rs +++ b/src/hg_connect_http.rs @@ -13,7 +13,7 @@ use std::path::{Path, PathBuf}; use std::ptr; use std::str::FromStr; use std::sync::mpsc::{channel, Receiver, Sender}; -use std::sync::Arc; +use std::sync::{Arc, OnceLock}; use std::thread::{self, JoinHandle}; use bstr::{BStr, ByteSlice}; @@ -49,6 +49,8 @@ use crate::util::{ImmutBString, OsStrExt, PrefixWriter, ReadExt, SeekExt, SliceE use self::git_http_state::{GitHttpStateToken, GIT_HTTP_STATE}; +pub static CURL_GLOBAL_INIT: OnceLock<()> = OnceLock::new(); + mod git_http_state { use std::{ffi::CString, ptr, sync::Mutex}; @@ -81,6 +83,13 @@ mod git_http_state { match &self.url { Some(url) if url == &normalized_url => {} _ => { + super::CURL_GLOBAL_INIT.get_or_init(|| { + if unsafe { curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL) } + != curl_sys::CURLE_OK + { + crate::die!("curl_global_init failed"); + } + }); let c_url = CString::new(normalized_url.to_string()).unwrap(); unsafe { if self.url.is_some() { diff --git a/src/http.c.patch b/src/http.c.patch index 89cf0f8ca..6f6f937ba 100644 --- a/src/http.c.patch +++ b/src/http.c.patch @@ -1,8 +1,8 @@ diff --git a/http.c b/http.c -index 2a722f6357..c7e0395abd 100644 +index 239421a983..8d1086ca4d 100644 --- a/http.c +++ b/http.c -@@ -63,7 +63,7 @@ static const char *curl_no_proxy; +@@ -68,7 +68,7 @@ static const char *curl_no_proxy; #ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY static const char *ssl_pinnedkey; #endif @@ -11,7 +11,7 @@ index 2a722f6357..c7e0395abd 100644 static long curl_low_speed_limit = -1; static long curl_low_speed_time = -1; static int curl_ftp_no_epsv; -@@ -288,11 +288,13 @@ static int http_options(const char *var, const char *value, void *cb) +@@ -406,11 +406,13 @@ static int http_options(const char *var, const char *value, curl_ssl_try = git_config_bool(var, value); return 0; } @@ -25,3 +25,21 @@ index 2a722f6357..c7e0395abd 100644 if (!strcmp("http.schannelcheckrevoke", var)) { if (value && !strcmp(value, "best-effort")) { +@@ -1300,9 +1302,6 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) + } + #endif + +- if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) +- die("curl_global_init failed"); +- + http_proactive_auth = proactive_auth; + + if (remote && remote->http_proxy) +@@ -1391,7 +1390,6 @@ void http_cleanup(void) + curl_easy_cleanup(curl_default); + + curl_multi_cleanup(curlm); +- curl_global_cleanup(); + + string_list_clear(&extra_http_headers, 0); + diff --git a/src/main.rs b/src/main.rs index b8dde71d7..167575e8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4242,6 +4242,12 @@ unsafe extern "C" fn cinnabar_main(_argc: c_int, argv: *const *const c_char) -> Some(_) | None => Ok(1), }; done_cinnabar(); + + if hg_connect_http::CURL_GLOBAL_INIT.get().is_some() { + unsafe { + curl_sys::curl_global_cleanup(); + } + } match ret { Ok(code) => code, Err(msg) => {