Skip to content

Commit ea385e2

Browse files
authored
Use a mutex to guard cert creation on windows (#11546)
- It should prevent some test flakyness around importing certs in some cases.
1 parent 9016794 commit ea385e2

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed
Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

4+
using System;
45
using System.IO;
6+
using System.Runtime.InteropServices;
57
using System.Security.Cryptography.X509Certificates;
8+
using System.Threading;
9+
using Xunit;
610

711
namespace Microsoft.AspNetCore.Testing
812
{
@@ -13,14 +17,28 @@ public static class TestResources
1317
public static string TestCertificatePath { get; } = Path.Combine(_baseDir, "testCert.pfx");
1418
public static string GetCertPath(string name) => Path.Combine(_baseDir, name);
1519

16-
public static X509Certificate2 GetTestCertificate()
17-
{
18-
return new X509Certificate2(TestCertificatePath, "testPassword");
19-
}
20+
private const int MutexTimeout = 120 * 1000;
21+
private static readonly Mutex importPfxMutex = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
22+
new Mutex(initiallyOwned: false, "Global\\KestrelTests.Certificates.LoadPfxCertificate") :
23+
null;
2024

21-
public static X509Certificate2 GetTestCertificate(string certName)
25+
public static X509Certificate2 GetTestCertificate(string certName = "testCert.pfx")
2226
{
23-
return new X509Certificate2(GetCertPath(certName), "testPassword");
27+
// On Windows, applications should not import PFX files in parallel to avoid a known system-level
28+
// race condition bug in native code which can cause crashes/corruption of the certificate state.
29+
if (importPfxMutex != null)
30+
{
31+
Assert.True(importPfxMutex.WaitOne(MutexTimeout), "Cannot acquire the global certificate mutex.");
32+
}
33+
34+
try
35+
{
36+
return new X509Certificate2(GetCertPath(certName), "testPassword");
37+
}
38+
finally
39+
{
40+
importPfxMutex?.ReleaseMutex();
41+
}
2442
}
2543
}
2644
}

0 commit comments

Comments
 (0)