@@ -20,7 +20,7 @@ use async_trait::async_trait;
20
20
use chrono:: { DateTime , Duration , Utc } ;
21
21
use gethostname:: gethostname;
22
22
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 } ;
24
24
use tokio:: time:: sleep;
25
25
use tunnels:: {
26
26
contracts:: PROD_FIRST_PARTY_APP_ID ,
@@ -210,6 +210,48 @@ const KEYCHAIN_ENTRY_LIMIT: usize = 128 * 1024;
210
210
211
211
const CONTINUE_MARKER : & str = "<MORE>" ;
212
212
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
+
213
255
#[ derive( Default ) ]
214
256
struct KeyringStorage {
215
257
// keywring storage can be split into multiple entries due to entry length limits
@@ -325,7 +367,10 @@ impl Auth {
325
367
return op ( s) ;
326
368
}
327
369
370
+ #[ cfg( not( target_os = "linux" ) ) ]
328
371
let mut keyring_storage = KeyringStorage :: default ( ) ;
372
+ #[ cfg( target_os = "linux" ) ]
373
+ let mut keyring_storage = ThreadKeyringStorage :: default ( ) ;
329
374
let mut file_storage = FileStorage ( PersistedState :: new ( self . file_storage_path . clone ( ) ) ) ;
330
375
331
376
let keyring_storage_result = match std:: env:: var ( "VSCODE_CLI_USE_FILE_KEYCHAIN" ) {
0 commit comments