@@ -412,6 +412,9 @@ private X509Certificate2 makeCertificate(string certificateName, bool isRootCert
412
412
return certificate ;
413
413
}
414
414
415
+ private static ConcurrentDictionary < string , object > saveCertificateLocks
416
+ = new ConcurrentDictionary < string , object > ( ) ;
417
+
415
418
/// <summary>
416
419
/// Create an SSL certificate
417
420
/// </summary>
@@ -445,7 +448,21 @@ private X509Certificate2 makeCertificate(string certificateName, bool isRootCert
445
448
446
449
try
447
450
{
448
- certificateCache . SaveCertificate ( subjectName , certificate ) ;
451
+ //acquire lock by subjectName
452
+ //Async lock is not needed. Since this is a rare race-condition
453
+ lock ( saveCertificateLocks . GetOrAdd ( subjectName , new object ( ) ) )
454
+ {
455
+ try
456
+ {
457
+ //no two tasks with same subject name should together enter here
458
+ certificateCache . SaveCertificate ( subjectName , certificate ) ;
459
+ }
460
+ finally
461
+ {
462
+ //save operation is complete. Free lock from memory.
463
+ saveCertificateLocks . TryRemove ( subjectName , out var _ ) ;
464
+ }
465
+ }
449
466
}
450
467
catch ( Exception e )
451
468
{
@@ -482,13 +499,17 @@ private X509Certificate2 makeCertificate(string certificateName, bool isRootCert
482
499
}
483
500
484
501
// handle burst requests with same certificate name
485
- // by checking for existing task for same certificate name
502
+ // by checking for existing task for same certificate name.
503
+ // If two or more requests hit this block at the same time, then multiple tasks will be created,
504
+ // which is okay. That certificate will be created twice or more. We don't anticipate many requests for same host at the same time.
505
+ // This saves us from another expensive lock. The goal here is to minimize creation of multiple tasks for same certification name.
506
+ // Goal is not to guarantee single certificate creation, which is not needed in our case.
486
507
if ( pendingCertificateCreationTasks . TryGetValue ( certificateName , out var task ) )
487
508
{
488
509
return await task ;
489
510
}
490
511
491
- // run certificate creation task & add it to pending tasks
512
+ // run certificate creation task & add it to pending tasks
492
513
task = Task . Run ( ( ) =>
493
514
{
494
515
var result = CreateCertificate ( certificateName , false ) ;
0 commit comments