Skip to content

Commit b881a32

Browse files
committed
fix: add OnceLock for LibSecretCredential
Previously, LibSecretCredential was created multiple times and with it libsecret was loaded and unloaded multiple times, leading to issues where calls could run indefinitely due to glib not properly cleaning up. Now, LibSecretCredential is stored in a OnceLock, ensuring it is only created once, preventing unnecessary unload/reload cycles of libsecret.
1 parent 22940c7 commit b881a32

File tree

2 files changed

+23
-2
lines changed
  • credential/cargo-credential-libsecret/src
  • src/cargo/util/auth

2 files changed

+23
-2
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ mod linux {
119119
}
120120
}
121121

122-
impl Credential for LibSecretCredential {
122+
impl Credential for &LibSecretCredential {
123123
fn perform(
124124
&self,
125125
registry: &RegistryInfo<'_>,

src/cargo/util/auth/mod.rs

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

511+
/// Retrieves a cached instance of `LibSecretCredential`.
512+
/// Must be cached to avoid repeated load/unload cycles, which are not supported by `glib`.
513+
#[cfg(target_os = "linux")]
514+
fn get_credential_libsecret(
515+
) -> CargoResult<&'static cargo_credential_libsecret::LibSecretCredential> {
516+
static CARGO_CREDENTIAL_LIBSECRET: std::sync::OnceLock<
517+
cargo_credential_libsecret::LibSecretCredential,
518+
> = std::sync::OnceLock::new();
519+
// Unfortunately `get_or_try_init` is not yet stable. This workaround is not threadsafe but
520+
// loading libsecret twice will only temporary increment the ref counter, which is decrement
521+
// again when `drop` is called.
522+
match CARGO_CREDENTIAL_LIBSECRET.get() {
523+
Some(lib) => Ok(lib),
524+
None => {
525+
let _ = CARGO_CREDENTIAL_LIBSECRET
526+
.set(cargo_credential_libsecret::LibSecretCredential::new()?);
527+
Ok(CARGO_CREDENTIAL_LIBSECRET.get().unwrap())
528+
}
529+
}
530+
}
531+
511532
fn credential_action(
512533
gctx: &GlobalContext,
513534
sid: &SourceId,
@@ -545,7 +566,7 @@ fn credential_action(
545566
#[cfg(target_os = "macos")]
546567
"cargo:macos-keychain" => Box::new(cargo_credential_macos_keychain::MacKeychain {}),
547568
#[cfg(target_os = "linux")]
548-
"cargo:libsecret" => Box::new(cargo_credential_libsecret::LibSecretCredential::new()?),
569+
"cargo:libsecret" => Box::new(get_credential_libsecret()?),
549570
name if BUILT_IN_PROVIDERS.contains(&name) => {
550571
Box::new(cargo_credential::UnsupportedCredential {})
551572
}

0 commit comments

Comments
 (0)