8
8
using System . Net ;
9
9
using System . Net . Http ;
10
10
using System . Net . Http . Headers ;
11
+ using System . Runtime . InteropServices ;
11
12
using System . Text ;
12
13
using System . Threading ;
13
14
using System . Threading . Tasks ;
@@ -27,9 +28,15 @@ public abstract class HttpRequestor : IDisposable
27
28
28
29
static HttpRequestor ( )
29
30
{
30
- ServicePointManager . SecurityProtocol = ServicePointManager . SecurityProtocol | SecurityProtocolType . Tls12 ;
31
- ServicePointManager . DefaultConnectionLimit = Environment . ProcessorCount ;
32
- availableConnections = new SemaphoreSlim ( ServicePointManager . DefaultConnectionLimit ) ;
31
+ /* If machine.config is locked, then initializing ServicePointManager will fail and be unrecoverable.
32
+ * Machine.config locking is typically very brief (~1ms by the antivirus scanner) so we can attempt to lock
33
+ * it ourselves (by opening it for read) *beforehand and briefly wait if it's locked */
34
+ using ( var machineConfigLock = GetMachineConfigLock ( ) )
35
+ {
36
+ ServicePointManager . SecurityProtocol = ServicePointManager . SecurityProtocol | SecurityProtocolType . Tls12 ;
37
+ ServicePointManager . DefaultConnectionLimit = Environment . ProcessorCount ;
38
+ availableConnections = new SemaphoreSlim ( ServicePointManager . DefaultConnectionLimit ) ;
39
+ }
33
40
}
34
41
35
42
protected HttpRequestor ( ITracer tracer , RetryConfig retryConfig , Enlistment enlistment )
@@ -329,5 +336,28 @@ private static bool TryGetResponseMessageFromHttpRequestException(HttpRequestExc
329
336
return true ;
330
337
331
338
}
339
+
340
+ private static FileStream GetMachineConfigLock ( )
341
+ {
342
+ var machineConfigLocation = RuntimeEnvironment . SystemConfigurationFile ;
343
+ var tries = 0 ;
344
+ var maxTries = 3 ;
345
+ while ( tries ++ < maxTries )
346
+ {
347
+ try
348
+ {
349
+ /* Opening with FileShare.Read will fail if another process (eg antivirus) has opened the file for write,
350
+ but will still let ServicePointManager read the file.*/
351
+ FileStream stream = File . Open ( machineConfigLocation , FileMode . Open , FileAccess . Read , FileShare . Read ) ;
352
+ return stream ;
353
+ }
354
+ catch ( IOException e ) when ( ( uint ) e . HResult == 0x80070020 ) // SHARING_VIOLATION
355
+ {
356
+ Thread . Sleep ( 10 ) ;
357
+ }
358
+ }
359
+ /* Couldn't get the lock - the process will likely fail. */
360
+ return null ;
361
+ }
332
362
}
333
363
}
0 commit comments