@@ -10,7 +10,8 @@ use crate::{
10
10
trace,
11
11
util:: {
12
12
errors:: {
13
- wrap, AnyError , OAuthError , RefreshTokenNotAvailableError , StatusError , WrappedError ,
13
+ wrap, AnyError , CodeError , OAuthError , RefreshTokenNotAvailableError , StatusError ,
14
+ WrappedError ,
14
15
} ,
15
16
input:: prompt_options,
16
17
} ,
@@ -172,9 +173,9 @@ pub struct Auth {
172
173
}
173
174
174
175
trait StorageImplementation : Send + Sync {
175
- fn read ( & mut self ) -> Result < Option < StoredCredential > , WrappedError > ;
176
- fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , WrappedError > ;
177
- fn clear ( & mut self ) -> Result < ( ) , WrappedError > ;
176
+ fn read ( & mut self ) -> Result < Option < StoredCredential > , AnyError > ;
177
+ fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , AnyError > ;
178
+ fn clear ( & mut self ) -> Result < ( ) , AnyError > ;
178
179
}
179
180
180
181
// unseal decrypts and deserializes the value
@@ -217,16 +218,34 @@ struct ThreadKeyringStorage {
217
218
}
218
219
219
220
impl ThreadKeyringStorage {
220
- fn thread_op < R , Fn > ( & mut self , f : Fn ) -> R
221
+ fn thread_op < R , Fn > ( & mut self , f : Fn ) -> Result < R , AnyError >
221
222
where
222
- Fn : ' static + Send + FnOnce ( & mut KeyringStorage ) -> R ,
223
+ Fn : ' static + Send + FnOnce ( & mut KeyringStorage ) -> Result < R , AnyError > ,
223
224
R : ' static + Send ,
224
225
{
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
226
+ let mut s = match self . s . take ( ) {
227
+ Some ( s) => s,
228
+ None => return Err ( CodeError :: KeyringTimeout . into ( ) ) ,
229
+ } ;
230
+
231
+ // It seems like on Linux communication to the keyring can block indefinitely.
232
+ // Fall back after a 5 second timeout.
233
+ let ( sender, receiver) = std:: sync:: mpsc:: channel ( ) ;
234
+ let tsender = sender. clone ( ) ;
235
+
236
+ thread:: spawn ( move || sender. send ( Some ( ( f ( & mut s) , s) ) ) ) ;
237
+ thread:: spawn ( move || {
238
+ thread:: sleep ( std:: time:: Duration :: from_secs ( 5 ) ) ;
239
+ let _ = tsender. send ( None ) ;
240
+ } ) ;
241
+
242
+ match receiver. recv ( ) . unwrap ( ) {
243
+ Some ( ( r, s) ) => {
244
+ self . s = Some ( s) ;
245
+ r
246
+ }
247
+ None => Err ( CodeError :: KeyringTimeout . into ( ) ) ,
248
+ }
230
249
}
231
250
}
232
251
@@ -239,15 +258,15 @@ impl Default for ThreadKeyringStorage {
239
258
}
240
259
241
260
impl StorageImplementation for ThreadKeyringStorage {
242
- fn read ( & mut self ) -> Result < Option < StoredCredential > , WrappedError > {
261
+ fn read ( & mut self ) -> Result < Option < StoredCredential > , AnyError > {
243
262
self . thread_op ( |s| s. read ( ) )
244
263
}
245
264
246
- fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , WrappedError > {
265
+ fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , AnyError > {
247
266
self . thread_op ( move |s| s. store ( value) )
248
267
}
249
268
250
- fn clear ( & mut self ) -> Result < ( ) , WrappedError > {
269
+ fn clear ( & mut self ) -> Result < ( ) , AnyError > {
251
270
self . thread_op ( |s| s. clear ( ) )
252
271
}
253
272
}
@@ -273,15 +292,15 @@ macro_rules! get_next_entry {
273
292
}
274
293
275
294
impl StorageImplementation for KeyringStorage {
276
- fn read ( & mut self ) -> Result < Option < StoredCredential > , WrappedError > {
295
+ fn read ( & mut self ) -> Result < Option < StoredCredential > , AnyError > {
277
296
let mut str = String :: new ( ) ;
278
297
279
298
for i in 0 .. {
280
299
let entry = get_next_entry ! ( self , i) ;
281
300
let next_chunk = match entry. get_password ( ) {
282
301
Ok ( value) => value,
283
302
Err ( keyring:: Error :: NoEntry ) => return Ok ( None ) , // missing entries?
284
- Err ( e) => return Err ( wrap ( e, "error reading keyring" ) ) ,
303
+ Err ( e) => return Err ( wrap ( e, "error reading keyring" ) . into ( ) ) ,
285
304
} ;
286
305
287
306
if next_chunk. ends_with ( CONTINUE_MARKER ) {
@@ -295,7 +314,7 @@ impl StorageImplementation for KeyringStorage {
295
314
Ok ( unseal ( & str) )
296
315
}
297
316
298
- fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , WrappedError > {
317
+ fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , AnyError > {
299
318
let sealed = seal ( & value) ;
300
319
let step_size = KEYCHAIN_ENTRY_LIMIT - CONTINUE_MARKER . len ( ) ;
301
320
@@ -312,14 +331,14 @@ impl StorageImplementation for KeyringStorage {
312
331
} ;
313
332
314
333
if let Err ( e) = stored {
315
- return Err ( wrap ( e, "error updating keyring" ) ) ;
334
+ return Err ( wrap ( e, "error updating keyring" ) . into ( ) ) ;
316
335
}
317
336
}
318
337
319
338
Ok ( ( ) )
320
339
}
321
340
322
- fn clear ( & mut self ) -> Result < ( ) , WrappedError > {
341
+ fn clear ( & mut self ) -> Result < ( ) , AnyError > {
323
342
self . read ( ) . ok ( ) ; // make sure component parts are available
324
343
for entry in self . entries . iter ( ) {
325
344
entry
@@ -335,16 +354,16 @@ impl StorageImplementation for KeyringStorage {
335
354
struct FileStorage ( PersistedState < Option < String > > ) ;
336
355
337
356
impl StorageImplementation for FileStorage {
338
- fn read ( & mut self ) -> Result < Option < StoredCredential > , WrappedError > {
357
+ fn read ( & mut self ) -> Result < Option < StoredCredential > , AnyError > {
339
358
Ok ( self . 0 . load ( ) . and_then ( |s| unseal ( & s) ) )
340
359
}
341
360
342
- fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , WrappedError > {
343
- self . 0 . save ( Some ( seal ( & value) ) )
361
+ fn store ( & mut self , value : StoredCredential ) -> Result < ( ) , AnyError > {
362
+ self . 0 . save ( Some ( seal ( & value) ) ) . map_err ( |e| e . into ( ) )
344
363
}
345
364
346
- fn clear ( & mut self ) -> Result < ( ) , WrappedError > {
347
- self . 0 . save ( None )
365
+ fn clear ( & mut self ) -> Result < ( ) , AnyError > {
366
+ self . 0 . save ( None ) . map_err ( |e| e . into ( ) )
348
367
}
349
368
}
350
369
@@ -374,7 +393,7 @@ impl Auth {
374
393
let mut file_storage = FileStorage ( PersistedState :: new ( self . file_storage_path . clone ( ) ) ) ;
375
394
376
395
let keyring_storage_result = match std:: env:: var ( "VSCODE_CLI_USE_FILE_KEYCHAIN" ) {
377
- Ok ( _) => Err ( wrap ( "" , "user prefers file storage" ) ) ,
396
+ Ok ( _) => Err ( wrap ( "" , "user prefers file storage" ) . into ( ) ) ,
378
397
_ => keyring_storage. read ( ) ,
379
398
} ;
380
399
@@ -383,10 +402,17 @@ impl Auth {
383
402
last_read : Cell :: new ( Ok ( v) ) ,
384
403
storage : Box :: new ( keyring_storage) ,
385
404
} ,
386
- Err ( _) => StorageWithLastRead {
387
- last_read : Cell :: new ( file_storage. read ( ) ) ,
388
- storage : Box :: new ( file_storage) ,
389
- } ,
405
+ Err ( e) => {
406
+ debug ! ( self . log, "Using file keychain storage due to: {}" , e) ;
407
+ StorageWithLastRead {
408
+ last_read : Cell :: new (
409
+ file_storage
410
+ . read ( )
411
+ . map_err ( |e| wrap ( e, "could not read from file storage" ) ) ,
412
+ ) ,
413
+ storage : Box :: new ( file_storage) ,
414
+ }
415
+ }
390
416
} ;
391
417
392
418
let out = op ( & mut storage) ;
@@ -419,7 +445,7 @@ impl Auth {
419
445
}
420
446
421
447
/// Clears login info from the keyring.
422
- pub fn clear_credentials ( & self ) -> Result < ( ) , WrappedError > {
448
+ pub fn clear_credentials ( & self ) -> Result < ( ) , AnyError > {
423
449
self . with_storage ( |storage| {
424
450
storage. storage . clear ( ) ?;
425
451
storage. last_read . set ( Ok ( None ) ) ;
0 commit comments