@@ -20,7 +20,7 @@ use async_trait::async_trait;
2020use chrono:: { DateTime , Duration , Utc } ;
2121use gethostname:: gethostname;
2222use 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 } ;
2424use tokio:: time:: sleep;
2525use tunnels:: {
2626 contracts:: PROD_FIRST_PARTY_APP_ID ,
@@ -210,6 +210,48 @@ const KEYCHAIN_ENTRY_LIMIT: usize = 128 * 1024;
210210
211211const 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 ) ]
214256struct 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