From 981a155934532cea2b9605cec1e4cd6eee0fc080 Mon Sep 17 00:00:00 2001 From: Saeed Noursalehi Date: Wed, 5 Sep 2018 12:22:27 -0700 Subject: [PATCH 1/7] Throw if a message is written to a disposed tracer --- GVFS/GVFS.Common/Tracing/JsonTracer.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/GVFS/GVFS.Common/Tracing/JsonTracer.cs b/GVFS/GVFS.Common/Tracing/JsonTracer.cs index 07e424b23..07fe4b01c 100644 --- a/GVFS/GVFS.Common/Tracing/JsonTracer.cs +++ b/GVFS/GVFS.Common/Tracing/JsonTracer.cs @@ -20,6 +20,9 @@ public class JsonTracer : ITracer private EventLevel startStopLevel; private Keywords startStopKeywords; + + private bool disposed; + public JsonTracer(string providerName, string activityName, bool disableTelemetry = false) : this(providerName, Guid.Empty, activityName, enlistmentId: null, mountId: null, disableTelemetry: disableTelemetry) { @@ -101,6 +104,8 @@ public void Dispose() this.listeners.Clear(); } + + this.disposed = true; } public virtual void RelatedEvent(EventLevel level, string eventName, EventMetadata metadata) @@ -256,6 +261,15 @@ private static string GetCategorizedErrorEventName(Keywords keywords) private void WriteEvent(string eventName, EventLevel level, Keywords keywords, EventMetadata metadata, EventOpcode opcode) { string jsonPayload = metadata != null ? JsonConvert.SerializeObject(metadata) : null; + + if (this.disposed) + { + Console.WriteLine("Writing to disposed tracer"); + Console.WriteLine(jsonPayload); + + throw new ObjectDisposedException(nameof(JsonTracer)); + } + foreach (InProcEventListener listener in this.listeners) { listener.RecordMessage(eventName, this.activityId, this.parentActivityId, level, keywords, opcode, jsonPayload); From 1a9e8c3edc32ab0224ee9c4806fde3e82b730c1f Mon Sep 17 00:00:00 2001 From: Saeed Noursalehi Date: Wed, 5 Sep 2018 12:23:32 -0700 Subject: [PATCH 2/7] Early exit if the named pipe is already disposed --- GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs b/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs index 91350dfcd..3b89baaba 100644 --- a/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs +++ b/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs @@ -87,7 +87,10 @@ private void OpenListeningPipe() private void OnNewConnection(IAsyncResult ar) { - this.OnNewConnection(ar, createNewThreadIfSynchronous: true); + if (!this.isStopping) + { + this.OnNewConnection(ar, createNewThreadIfSynchronous: true); + } } private void OnNewConnection(IAsyncResult ar, bool createNewThreadIfSynchronous) From dc4a5f6075f2b23a4c4b0091e85c26b6bafb387f Mon Sep 17 00:00:00 2001 From: Saeed Noursalehi Date: Wed, 5 Sep 2018 12:24:02 -0700 Subject: [PATCH 3/7] Clarify a warning message that gets logged during prefetch if the mount process is not running --- GVFS/GVFS.Common/Prefetch/CommitPrefetcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GVFS/GVFS.Common/Prefetch/CommitPrefetcher.cs b/GVFS/GVFS.Common/Prefetch/CommitPrefetcher.cs index eb2237cbc..ebe943ee0 100644 --- a/GVFS/GVFS.Common/Prefetch/CommitPrefetcher.cs +++ b/GVFS/GVFS.Common/Prefetch/CommitPrefetcher.cs @@ -155,7 +155,7 @@ private static bool TrySchedulePostFetchJob(ITracer tracer, string namedPipeName { tracer.RelatedWarning( metadata: null, - message: "Failed to connect to GVFS. Skipping post-fetch job request.", + message: "Failed to connect to GVFS.Mount process. Skipping post-fetch job request.", keywords: Keywords.Telemetry); return false; } From 3162792c53d792d4bf3c8934d88ad322084da871 Mon Sep 17 00:00:00 2001 From: Saeed Noursalehi Date: Wed, 5 Sep 2018 14:55:04 -0700 Subject: [PATCH 4/7] No longer need to handle ObjectDisposedException on Windows --- GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs b/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs index 3b89baaba..d6eebe711 100644 --- a/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs +++ b/GVFS/GVFS.Common/NamedPipes/NamedPipeServer.cs @@ -126,13 +126,6 @@ private void OnNewConnection(IAsyncResult ar, bool createNewThreadIfSynchronous) metadata.Add(TracingConstants.MessageKey.WarningMessage, "OnNewConnection: Connection broken"); this.tracer.RelatedEvent(EventLevel.Warning, "OnNewConnectionn_EndWaitForConnection_IOException", metadata); } - catch (ObjectDisposedException) - { - if (!this.isStopping) - { - throw; - } - } catch (Exception e) { this.LogErrorAndExit("OnNewConnection caught unhandled exception, exiting process", e); From 0c55441362b6c467a58216a8ce107e0dbc249b8b Mon Sep 17 00:00:00 2001 From: Saeed Noursalehi Date: Wed, 5 Sep 2018 15:28:39 -0700 Subject: [PATCH 5/7] Don't pass --no-mount and --no-prefetch flags to clone, because it can hide bugs --- GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs | 1 - GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs | 2 +- Scripts/Mac/RunFunctionalTests.sh | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs index d1f1734b3..9ca2bc7e9 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs @@ -157,7 +157,6 @@ public void CloneAndMount() { this.gvfsProcess.Clone(this.RepoUrl, this.Commitish); - this.MountGVFS(); GitProcess.Invoke(this.RepoRoot, "checkout " + this.Commitish); GitProcess.Invoke(this.RepoRoot, "branch --unset-upstream"); GitProcess.Invoke(this.RepoRoot, "config core.abbrev 40"); diff --git a/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs b/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs index 1743670e2..b0d6aea85 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs @@ -21,7 +21,7 @@ public GVFSProcess(string pathToGVFS, string enlistmentRoot, string localCacheRo public void Clone(string repositorySource, string branchToCheckout) { string args = string.Format( - "clone \"{0}\" \"{1}\" --branch \"{2}\" --no-mount --no-prefetch --local-cache-path \"{3}\"", + "clone \"{0}\" \"{1}\" --branch \"{2}\" --local-cache-path \"{3}\"", repositorySource, this.enlistmentRoot, branchToCheckout, diff --git a/Scripts/Mac/RunFunctionalTests.sh b/Scripts/Mac/RunFunctionalTests.sh index bc84e8a18..627f8a3c7 100755 --- a/Scripts/Mac/RunFunctionalTests.sh +++ b/Scripts/Mac/RunFunctionalTests.sh @@ -15,4 +15,4 @@ sudo mkdir /GVFS.FT sudo chown $USER /GVFS.FT $SRCDIR/ProjFS.Mac/Scripts/LoadPrjFSKext.sh -$PUBLISHDIR/GVFS.FunctionalTests --full-suite +$PUBLISHDIR/GVFS.FunctionalTests --full-suite $2 From e6bd6b1262c87ed7ecddee6c18aaa7a6de4b316d Mon Sep 17 00:00:00 2001 From: Saeed Noursalehi Date: Wed, 5 Sep 2018 21:25:32 -0700 Subject: [PATCH 6/7] Allow the prefetch tests to skip prefetch during clone --- .../PrefetchVerbWithoutSharedCacheTests.cs | 2 +- .../TestsWithEnlistmentPerFixture.cs | 6 ++++-- .../Tools/GVFSFunctionalTestEnlistment.cs | 12 ++++++------ GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs | 9 ++++----- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/PrefetchVerbWithoutSharedCacheTests.cs b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/PrefetchVerbWithoutSharedCacheTests.cs index a64bae950..2ee1da2f7 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/PrefetchVerbWithoutSharedCacheTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/PrefetchVerbWithoutSharedCacheTests.cs @@ -22,7 +22,7 @@ public class PrefetchVerbWithoutSharedCacheTests : TestsWithEnlistmentPerFixture // Set forcePerRepoObjectCache to true to avoid any of the tests inadvertently corrupting // the cache public PrefetchVerbWithoutSharedCacheTests() - : base(forcePerRepoObjectCache: true) + : base(forcePerRepoObjectCache: true, skipPrefetchDuringClone: true) { this.fileSystem = new SystemIORunner(); } diff --git a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/TestsWithEnlistmentPerFixture.cs b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/TestsWithEnlistmentPerFixture.cs index b8bc7a9c3..fd5d798fd 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/TestsWithEnlistmentPerFixture.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/EnlistmentPerFixture/TestsWithEnlistmentPerFixture.cs @@ -7,10 +7,12 @@ namespace GVFS.FunctionalTests.Tests.EnlistmentPerFixture public abstract class TestsWithEnlistmentPerFixture { private readonly bool forcePerRepoObjectCache; + private readonly bool skipPrefetchDuringClone; - public TestsWithEnlistmentPerFixture(bool forcePerRepoObjectCache = false) + public TestsWithEnlistmentPerFixture(bool forcePerRepoObjectCache = false, bool skipPrefetchDuringClone = false) { this.forcePerRepoObjectCache = forcePerRepoObjectCache; + this.skipPrefetchDuringClone = skipPrefetchDuringClone; } public GVFSFunctionalTestEnlistment Enlistment @@ -23,7 +25,7 @@ public virtual void CreateEnlistment() { if (this.forcePerRepoObjectCache) { - this.Enlistment = GVFSFunctionalTestEnlistment.CloneAndMountWithPerRepoCache(GVFSTestConfig.PathToGVFS); + this.Enlistment = GVFSFunctionalTestEnlistment.CloneAndMountWithPerRepoCache(GVFSTestConfig.PathToGVFS, this.skipPrefetchDuringClone); } else { diff --git a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs index 9ca2bc7e9..427fef7b2 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GVFSFunctionalTestEnlistment.cs @@ -82,11 +82,11 @@ public string Commitish get; private set; } - public static GVFSFunctionalTestEnlistment CloneAndMountWithPerRepoCache(string pathToGvfs, string commitish = null) + public static GVFSFunctionalTestEnlistment CloneAndMountWithPerRepoCache(string pathToGvfs, bool skipPrefetch) { string enlistmentRoot = GVFSFunctionalTestEnlistment.GetUniqueEnlistmentRoot(); string localCache = GVFSFunctionalTestEnlistment.GetRepoSpecificLocalCacheRoot(enlistmentRoot); - return CloneAndMount(pathToGvfs, enlistmentRoot, commitish, localCache); + return CloneAndMount(pathToGvfs, enlistmentRoot, null, localCache, skipPrefetch); } public static GVFSFunctionalTestEnlistment CloneAndMount(string pathToGvfs, string commitish = null, string localCacheRoot = null) @@ -153,9 +153,9 @@ public void DeleteEnlistment() } } - public void CloneAndMount() + public void CloneAndMount(bool skipPrefetch) { - this.gvfsProcess.Clone(this.RepoUrl, this.Commitish); + this.gvfsProcess.Clone(this.RepoUrl, this.Commitish, skipPrefetch); GitProcess.Invoke(this.RepoRoot, "checkout " + this.Commitish); GitProcess.Invoke(this.RepoRoot, "branch --unset-upstream"); @@ -264,7 +264,7 @@ public string GetObjectPathTo(string objectHash) objectHash.Substring(2)); } - private static GVFSFunctionalTestEnlistment CloneAndMount(string pathToGvfs, string enlistmentRoot, string commitish, string localCacheRoot) + private static GVFSFunctionalTestEnlistment CloneAndMount(string pathToGvfs, string enlistmentRoot, string commitish, string localCacheRoot, bool skipPrefetch = false) { GVFSFunctionalTestEnlistment enlistment = new GVFSFunctionalTestEnlistment( pathToGvfs, @@ -275,7 +275,7 @@ private static GVFSFunctionalTestEnlistment CloneAndMount(string pathToGvfs, str try { - enlistment.CloneAndMount(); + enlistment.CloneAndMount(skipPrefetch); } catch (Exception e) { diff --git a/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs b/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs index b0d6aea85..5bcfd9049 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs @@ -1,7 +1,5 @@ using GVFS.Tests.Should; -using System; using System.Diagnostics; -using System.Runtime.InteropServices; namespace GVFS.FunctionalTests.Tools { @@ -18,14 +16,15 @@ public GVFSProcess(string pathToGVFS, string enlistmentRoot, string localCacheRo this.localCacheRoot = localCacheRoot; } - public void Clone(string repositorySource, string branchToCheckout) + public void Clone(string repositorySource, string branchToCheckout, bool skipPrefetch) { string args = string.Format( - "clone \"{0}\" \"{1}\" --branch \"{2}\" --local-cache-path \"{3}\"", + "clone \"{0}\" \"{1}\" --branch \"{2}\" --local-cache-path \"{3}\" {4}", repositorySource, this.enlistmentRoot, branchToCheckout, - this.localCacheRoot); + this.localCacheRoot, + skipPrefetch ? "--no-prefetch" : string.Empty); this.CallGVFS(args, failOnError: true); } From f781b9e79a23fcebf5f725b2cdfc62a7e233963f Mon Sep 17 00:00:00 2001 From: Saeed Noursalehi Date: Thu, 6 Sep 2018 10:08:59 -0700 Subject: [PATCH 7/7] Plumb the internal service name to all GVFS verbs. Otherwise automount during clone talks to the installed service, not the test instance. --- .../MultiEnlistmentTests/ServiceVerbTests.cs | 1 - .../TestsWithMultiEnlistment.cs | 1 - .../GVFS.FunctionalTests/Tools/GVFSProcess.cs | 24 ++++--------------- GVFS/GVFS/CommandLine/GVFSVerb.cs | 1 - 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/ServiceVerbTests.cs b/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/ServiceVerbTests.cs index 4015f54e0..161a3ab54 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/ServiceVerbTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/ServiceVerbTests.cs @@ -1,7 +1,6 @@ using GVFS.FunctionalTests.Tools; using GVFS.Tests.Should; using NUnit.Framework; -using System.IO; namespace GVFS.FunctionalTests.Tests.MultiEnlistmentTests { diff --git a/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/TestsWithMultiEnlistment.cs b/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/TestsWithMultiEnlistment.cs index 5becccdcb..f0afd9399 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/TestsWithMultiEnlistment.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/MultiEnlistmentTests/TestsWithMultiEnlistment.cs @@ -1,7 +1,6 @@ using GVFS.FunctionalTests.Tools; using NUnit.Framework; using System.Collections.Generic; -using System.IO; namespace GVFS.FunctionalTests.Tests.MultiEnlistmentTests { diff --git a/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs b/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs index 5bcfd9049..51f466bb4 100644 --- a/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs +++ b/GVFS/GVFS.FunctionalTests/Tools/GVFSProcess.cs @@ -37,10 +37,8 @@ public void Mount() public bool TryMount(out string output) { - string mountCommand = "mount \"" + this.enlistmentRoot + "\" --internal_use_only_service_name " + GVFSServiceProcess.TestServiceName; - this.IsEnlistmentMounted().ShouldEqual(false, "GVFS is already mounted"); - output = this.CallGVFS(mountCommand); + output = this.CallGVFS("mount \"" + this.enlistmentRoot + "\""); return this.IsEnlistmentMounted(); } @@ -58,11 +56,7 @@ public void Repair() public string Diagnose() { - string diagnoseArgs = string.Join( - " ", - "diagnose \"" + this.enlistmentRoot + "\"", - "--internal_use_only_service_name " + GVFSServiceProcess.TestServiceName); - return this.CallGVFS(diagnoseArgs); + return this.CallGVFS("diagnose \"" + this.enlistmentRoot + "\""); } public string Status() @@ -79,11 +73,7 @@ public void Unmount() { if (this.IsEnlistmentMounted()) { - string unmountArgs = string.Join( - " ", - "unmount \"" + this.enlistmentRoot + "\"", - "--internal_use_only_service_name " + GVFSServiceProcess.TestServiceName); - string result = this.CallGVFS(unmountArgs, failOnError: true); + string result = this.CallGVFS("unmount \"" + this.enlistmentRoot + "\"", failOnError: true); this.IsEnlistmentMounted().ShouldEqual(false, "GVFS did not unmount: " + result); } } @@ -96,18 +86,14 @@ public bool IsEnlistmentMounted() public string RunServiceVerb(string argument) { - string serviceVerbArgs = string.Join( - " ", - "service " + argument, - "--internal_use_only_service_name " + GVFSServiceProcess.TestServiceName); - return this.CallGVFS(serviceVerbArgs, failOnError: true); + return this.CallGVFS("service " + argument, failOnError: true); } private string CallGVFS(string args, bool failOnError = false) { ProcessStartInfo processInfo = null; processInfo = new ProcessStartInfo(this.pathToGVFS); - processInfo.Arguments = args; + processInfo.Arguments = args + " --internal_use_only_service_name " + GVFSServiceProcess.TestServiceName; processInfo.WindowStyle = ProcessWindowStyle.Hidden; processInfo.UseShellExecute = false; diff --git a/GVFS/GVFS/CommandLine/GVFSVerb.cs b/GVFS/GVFS/CommandLine/GVFSVerb.cs index 945682c40..dbb9440d6 100644 --- a/GVFS/GVFS/CommandLine/GVFSVerb.cs +++ b/GVFS/GVFS/CommandLine/GVFSVerb.cs @@ -7,7 +7,6 @@ using GVFS.Common.Tracing; using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Security;