Skip to content

Commit 9603246

Browse files
authored
Merge pull request #1828 from microsoft/milestones/m250
[Release] Milestone M250
2 parents 526710b + 720e23c commit 9603246

File tree

5 files changed

+51
-7
lines changed

5 files changed

+51
-7
lines changed

GVFS/GVFS.Common/Http/HttpRequestor.cs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Net;
99
using System.Net.Http;
1010
using System.Net.Http.Headers;
11+
using System.Runtime.InteropServices;
1112
using System.Text;
1213
using System.Threading;
1314
using System.Threading.Tasks;
@@ -27,9 +28,15 @@ public abstract class HttpRequestor : IDisposable
2728

2829
static HttpRequestor()
2930
{
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+
}
3340
}
3441

3542
protected HttpRequestor(ITracer tracer, RetryConfig retryConfig, Enlistment enlistment)
@@ -329,5 +336,28 @@ private static bool TryGetResponseMessageFromHttpRequestException(HttpRequestExc
329336
return true;
330337

331338
}
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+
}
332362
}
333363
}

GVFS/GVFS.Installers/GVFS.Installers.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</ItemDefinitionGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="Tools.InnoSetup" Version="6.2.1" />
15+
<PackageReference Include="Tools.InnoSetup" Version="6.3.1" />
1616
<PackageReference Include="GitForWindows.GVFS.Installer" Version="$(GitPackageVersion)" />
1717
<PackageReference Include="GitForWindows.GVFS.Portable" Version="$(GitPackageVersion)" />
1818
<PackageReference Include="MicroBuild.Core" Version="0.2.0" ExcludeAssets="none" />

GVFS/GVFS.Installers/Setup.iss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ MinVersion=10.0.14374
3939
DisableDirPage=yes
4040
DisableReadyPage=yes
4141
SetupIconFile="{#LayoutDir}\GitVirtualFileSystem.ico"
42-
ArchitecturesInstallIn64BitMode=x64
43-
ArchitecturesAllowed=x64
42+
ArchitecturesInstallIn64BitMode=x64compatible
43+
ArchitecturesAllowed=x64compatible
4444
WizardImageStretch=no
4545
WindowResizable=no
4646
CloseApplications=yes

GVFS/GitHooksLoader/GitHooksLoader.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ int ExecuteHook(const std::wstring &applicationName, wchar_t *hookName, int argc
117117
si.dwFlags = STARTF_USESTDHANDLES;
118118

119119
ZeroMemory(&pi, sizeof(pi));
120+
121+
/* The child process will inherit ErrorMode from this process.
122+
* SEM_FAILCRITICALERRORS will prevent the .NET runtime from
123+
* creating a dialog box for critical errors - in particular
124+
* if antivirus has locked the machine.config file.
125+
* Disabling the dialog box lets the child process (typically GVFS.Hooks.exe)
126+
* continue trying to run, and if it still needs machine.config then it
127+
* can handle the exception at that time (whereas the dialog box would
128+
* hang the app until clicked, and is not handleable by our code).
129+
*/
130+
UINT previousErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
131+
120132
if (!CreateProcess(
121133
NULL, // Application name
122134
const_cast<LPWSTR>(commandLine.c_str()),
@@ -131,8 +143,10 @@ int ExecuteHook(const std::wstring &applicationName, wchar_t *hookName, int argc
131143
)
132144
{
133145
fwprintf(stderr, L"Could not execute '%s'. CreateProcess error (%d).\n", applicationName.c_str(), GetLastError());
146+
SetErrorMode(previousErrorMode);
134147
exit(3);
135148
}
149+
SetErrorMode(previousErrorMode);
136150

137151
// Wait until child process exits.
138152
WaitForSingleObject(pi.hProcess, INFINITE);

scripts/Build.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ IF NOT EXIST "%NUGET_EXEC%" (
4343

4444
REM Acquire vswhere to find VS installations reliably
4545
SET VSWHERE_VER=2.6.7
46-
"%NUGET_EXEC%" install vswhere -Version %VSWHERE_VER% || exit /b 1
46+
"%NUGET_EXEC%" install vswhere -Version %VSWHERE_VER% -OutputDirectory %VFS_PACKAGESDIR% || exit /b 1
4747
SET VSWHERE_EXEC="%VFS_PACKAGESDIR%\vswhere.%VSWHERE_VER%\tools\vswhere.exe"
4848

4949
REM Assumes default installation location for Windows 10 SDKs

0 commit comments

Comments
 (0)