Skip to content

Commit b8a0b68

Browse files
committed
load libsecret only once
Previously, libsecret was loaded and unloaded multiple times, leading to issues where calls could run indefinitely due to glib not properly cleaning up. Now, libsecret is stored in a OnceLock, ensuring it is only loaded once, preventing unnecessary unload/reload cycles.
1 parent 64a1246 commit b8a0b68

File tree

5 files changed

+48
-19
lines changed

5 files changed

+48
-19
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ blake3 = "1.5.5"
2727
build-rs = { version = "0.3.1", path = "crates/build-rs" }
2828
cargo = { path = "" }
2929
cargo-credential = { version = "0.4.2", path = "credential/cargo-credential" }
30-
cargo-credential-libsecret = { version = "0.4.15", path = "credential/cargo-credential-libsecret" }
30+
cargo-credential-libsecret = { version = "0.5.0", path = "credential/cargo-credential-libsecret" }
3131
cargo-credential-macos-keychain = { version = "0.4.15", path = "credential/cargo-credential-macos-keychain" }
3232
cargo-credential-wincred = { version = "0.4.15", path = "credential/cargo-credential-wincred" }
3333
cargo-platform = { path = "crates/cargo-platform", version = "0.3.0" }
@@ -185,6 +185,7 @@ jiff.workspace = true
185185
jobserver.workspace = true
186186
lazycell.workspace = true
187187
libgit2-sys.workspace = true
188+
libloading.workspace = true
188189
memchr.workspace = true
189190
opener.workspace = true
190191
os_info.workspace = true

credential/cargo-credential-libsecret/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cargo-credential-libsecret"
3-
version = "0.4.15"
3+
version = "0.5.0"
44
rust-version = "1.87" # MSRV:1
55
edition.workspace = true
66
license.workspace = true

credential/cargo-credential-libsecret/src/lib.rs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
mod linux {
77
//! Implementation of the libsecret credential helper.
88
9-
use anyhow::Context;
109
use cargo_credential::{
1110
read_token, Action, CacheControl, Credential, CredentialResponse, Error, RegistryInfo,
1211
Secret,
@@ -83,7 +82,9 @@ mod linux {
8382
...
8483
) -> *mut gchar;
8584

86-
pub struct LibSecretCredential;
85+
pub struct LibSecretCredential<'a> {
86+
libsecret: &'a Library,
87+
}
8788

8889
fn label(index_url: &str) -> CString {
8990
CString::new(format!("cargo-registry:{}", index_url)).unwrap()
@@ -105,31 +106,35 @@ mod linux {
105106
}
106107
}
107108

108-
impl Credential for LibSecretCredential {
109+
impl<'a> LibSecretCredential<'a> {
110+
pub fn new(libsecret: &'a Library) -> LibSecretCredential<'a> {
111+
Self { libsecret }
112+
}
113+
}
114+
115+
impl Credential for LibSecretCredential<'_> {
109116
fn perform(
110117
&self,
111118
registry: &RegistryInfo<'_>,
112119
action: &Action<'_>,
113120
_args: &[&str],
114121
) -> Result<CredentialResponse, Error> {
115-
// Dynamically load libsecret to avoid users needing to install
116-
// additional -dev packages when building this provider.
117-
let lib;
118122
let secret_password_lookup_sync: Symbol<'_, SecretPasswordLookupSync>;
119123
let secret_password_store_sync: Symbol<'_, SecretPasswordStoreSync>;
120124
let secret_password_clear_sync: Symbol<'_, SecretPasswordClearSync>;
121125
unsafe {
122-
lib = Library::new("libsecret-1.so.0").context(
123-
"failed to load libsecret: try installing the `libsecret` \
124-
or `libsecret-1-0` package with the system package manager",
125-
)?;
126-
secret_password_lookup_sync = lib
126+
secret_password_lookup_sync = self
127+
.libsecret
127128
.get(b"secret_password_lookup_sync\0")
128129
.map_err(Box::new)?;
129-
secret_password_store_sync =
130-
lib.get(b"secret_password_store_sync\0").map_err(Box::new)?;
131-
secret_password_clear_sync =
132-
lib.get(b"secret_password_clear_sync\0").map_err(Box::new)?;
130+
secret_password_store_sync = self
131+
.libsecret
132+
.get(b"secret_password_store_sync\0")
133+
.map_err(Box::new)?;
134+
secret_password_clear_sync = self
135+
.libsecret
136+
.get(b"secret_password_clear_sync\0")
137+
.map_err(Box::new)?;
133138
}
134139

135140
let index_url_c = CString::new(registry.index_url).unwrap();

src/cargo/util/auth/mod.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,26 @@ static BUILT_IN_PROVIDERS: &[&'static str] = &[
508508
"cargo:libsecret",
509509
];
510510

511+
#[cfg(target_os = "linux")]
512+
fn get_libsecret() -> CargoResult<&'static libloading::Library> {
513+
// Dynamically load libsecret to avoid users needing to install additional -dev packages.
514+
// OnceLock to prevent multiple load/unload cycles (which glib does not support).
515+
static LIBSECRET: std::sync::OnceLock<libloading::Library> = std::sync::OnceLock::new();
516+
// unfortunately `get_or_try_init` is not yet stable
517+
match LIBSECRET.get() {
518+
Some(lib) => Ok(lib),
519+
None => {
520+
let _ = LIBSECRET.set(
521+
unsafe { libloading::Library::new("libsecret-1.so.0") }.context(
522+
"failed to load libsecret: try installing the `libsecret` \
523+
or `libsecret-1-0` package with the system package manager",
524+
)?,
525+
);
526+
Ok(LIBSECRET.get().unwrap())
527+
}
528+
}
529+
}
530+
511531
fn credential_action(
512532
gctx: &GlobalContext,
513533
sid: &SourceId,
@@ -545,7 +565,9 @@ fn credential_action(
545565
#[cfg(target_os = "macos")]
546566
"cargo:macos-keychain" => Box::new(cargo_credential_macos_keychain::MacKeychain {}),
547567
#[cfg(target_os = "linux")]
548-
"cargo:libsecret" => Box::new(cargo_credential_libsecret::LibSecretCredential {}),
568+
"cargo:libsecret" => Box::new(cargo_credential_libsecret::LibSecretCredential::new(
569+
get_libsecret()?,
570+
)),
549571
name if BUILT_IN_PROVIDERS.contains(&name) => {
550572
Box::new(cargo_credential::UnsupportedCredential {})
551573
}

0 commit comments

Comments
 (0)