From e9566fe07bbc09de372ab14f8e6f3d9cc6f0c641 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 15 Dec 2023 10:09:10 +0900 Subject: [PATCH] Only ever call curl_global_cleanup once See https://github.com/curl/curl/issues/12525. --- src/hg_connect_http.rs | 11 ++++++++++- src/http.c.patch | 24 +++++++++++++++++++++--- src/main.rs | 6 ++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/hg_connect_http.rs b/src/hg_connect_http.rs index c0339d20f..4142797c6 100644 --- a/src/hg_connect_http.rs +++ b/src/hg_connect_http.rs @@ -31,7 +31,7 @@ use curl_sys::{ use either::Either; use flate2::read::ZlibDecoder; use itertools::Itertools; -use once_cell::sync::Lazy; +use once_cell::sync::{Lazy, OnceCell}; use url::{form_urlencoded, Url}; use zstd::stream::read::Decoder as ZstdDecoder; @@ -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: OnceCell<()> = OnceCell::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 + { + 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) => {