Skip to content

Commit 13b1b90

Browse files
authored
tunnel: fix keyring panic on Linux (microsoft#185066)
tunnel: fix keyring panic on Linxu Fixes microsoft#184792 Reported on open-source-cooperative/keyring-rs#132
1 parent 9a8c0b6 commit 13b1b90

File tree

1 file changed

+46
-1
lines changed

1 file changed

+46
-1
lines changed

cli/src/auth.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use async_trait::async_trait;
2020
use chrono::{DateTime, Duration, Utc};
2121
use gethostname::gethostname;
2222
use serde::{de::DeserializeOwned, Deserialize, Serialize};
23-
use std::{cell::Cell, fmt::Display, path::PathBuf, sync::Arc};
23+
use std::{cell::Cell, fmt::Display, path::PathBuf, sync::Arc, thread};
2424
use tokio::time::sleep;
2525
use tunnels::{
2626
contracts::PROD_FIRST_PARTY_APP_ID,
@@ -210,6 +210,48 @@ const KEYCHAIN_ENTRY_LIMIT: usize = 128 * 1024;
210210

211211
const CONTINUE_MARKER: &str = "<MORE>";
212212

213+
/// Implementation that wraps the KeyringStorage on Linux to avoid
214+
/// https://github.com/hwchen/keyring-rs/issues/132
215+
struct ThreadKeyringStorage {
216+
s: Option<KeyringStorage>,
217+
}
218+
219+
impl ThreadKeyringStorage {
220+
fn thread_op<R, Fn>(&mut self, f: Fn) -> R
221+
where
222+
Fn: 'static + Send + FnOnce(&mut KeyringStorage) -> R,
223+
R: 'static + Send,
224+
{
225+
let mut s = self.s.take().unwrap();
226+
let handler = thread::spawn(move || (f(&mut s), s));
227+
let (r, s) = handler.join().unwrap();
228+
self.s = Some(s);
229+
r
230+
}
231+
}
232+
233+
impl Default for ThreadKeyringStorage {
234+
fn default() -> Self {
235+
Self {
236+
s: Some(KeyringStorage::default()),
237+
}
238+
}
239+
}
240+
241+
impl StorageImplementation for ThreadKeyringStorage {
242+
fn read(&mut self) -> Result<Option<StoredCredential>, WrappedError> {
243+
self.thread_op(|s| s.read())
244+
}
245+
246+
fn store(&mut self, value: StoredCredential) -> Result<(), WrappedError> {
247+
self.thread_op(move |s| s.store(value))
248+
}
249+
250+
fn clear(&mut self) -> Result<(), WrappedError> {
251+
self.thread_op(|s| s.clear())
252+
}
253+
}
254+
213255
#[derive(Default)]
214256
struct KeyringStorage {
215257
// keywring storage can be split into multiple entries due to entry length limits
@@ -325,7 +367,10 @@ impl Auth {
325367
return op(s);
326368
}
327369

370+
#[cfg(not(target_os = "linux"))]
328371
let mut keyring_storage = KeyringStorage::default();
372+
#[cfg(target_os = "linux")]
373+
let mut keyring_storage = ThreadKeyringStorage::default();
329374
let mut file_storage = FileStorage(PersistedState::new(self.file_storage_path.clone()));
330375

331376
let keyring_storage_result = match std::env::var("VSCODE_CLI_USE_FILE_KEYCHAIN") {

0 commit comments

Comments
 (0)