{"action":"created","issue":{"url":"https://api.github.com/repos/nunit/nunit/issues/1270","repository_url":"https://api.github.com/repos/nunit/nunit","labels_url":"https://api.github.com/repos/nunit/nunit/issues/1270/labels{/name}","comments_url":"https://api.github.com/repos/nunit/nunit/issues/1270/comments","events_url":"https://api.github.com/repos/nunit/nunit/issues/1270/events","html_url":"https://github.com/nunit/nunit/issues/1270","id":133622400,"number":1270,"title":"ITestRunner.Load() fails loading Nunit30Settings.xml when called in parallel","user":{"login":"bretehlert","id":2160420,"avatar_url":"https://avatars.githubusercontent.com/u/2160420?v=3","gravatar_id":"","url":"https://api.github.com/users/bretehlert","html_url":"https://github.com/bretehlert","followers_url":"https://api.github.com/users/bretehlert/followers","following_url":"https://api.github.com/users/bretehlert/following{/other_user}","gists_url":"https://api.github.com/users/bretehlert/gists{/gist_id}","starred_url":"https://api.github.com/users/bretehlert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bretehlert/subscriptions","organizations_url":"https://api.github.com/users/bretehlert/orgs","repos_url":"https://api.github.com/users/bretehlert/repos","events_url":"https://api.github.com/users/bretehlert/events{/privacy}","received_events_url":"https://api.github.com/users/bretehlert/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2016-02-15T04:51:16Z","updated_at":"2016-02-15T22:38:50Z","closed_at":null,"body":"When using nunit.engine.api 3.0.1 and executing test discovery in parallel in different processes on the same machine we get the following error loading Nunit30Settings.xml:\r\n\r\nNUnit.Engine.NUnitEngineException: Error loading settings C:\\Users\\s_datservice\\AppData\\Local\\NUnit\\Nunit30Settings.xml. The process cannot access the file 'C:\\Users\\s_datservice\\AppData\\Local\\NUnit\\Nunit30Settings.xml' because it is being used by another process. ---> System.IO.IOException: The process cannot access the file 'C:\\Users\\s_datservice\\AppData\\Local\\NUnit\\Nunit30Settings.xml' because it is being used by another process.\r\n   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)\r\n   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)\r\n   at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials, IWebProxy proxy, RequestCachePolicy cachePolicy)\r\n   at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)\r\n   at System.Xml.XmlTextReaderImpl.OpenUrlDelegate(Object xmlResolver)\r\n   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)\r\n   at System.Threading.CompressedStack.Run(CompressedStack compressedStack, ContextCallback callback, Object state)\r\n   at System.Xml.XmlTextReaderImpl.OpenUrl()\r\n   at System.Xml.XmlTextReaderImpl.Read()\r\n   at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)\r\n   at System.Xml.XmlDocument.Load(XmlReader reader)\r\n   at System.Xml.XmlDocument.Load(String filename)\r\n   at NUnit.Engine.Internal.SettingsStore.LoadSettings()\r\n   --- End of inner exception stack trace ---\r\n   at NUnit.Engine.Internal.SettingsStore.LoadSettings()\r\n   at NUnit.Engine.Services.SettingsService.StartService()\r\n   at NUnit.Engine.Services.ServiceManager.StartServices()\r\n   at NUnit.Agent.NUnitTestAgent.Main(String[] args)\r\nSystem.Exception: Unable to acquire remote process agent\r\n   at NUnit.Engine.Runners.ProcessRunner.LoadPackage()\r\n   at NUnit.Engine.Runners.AbstractTestRunner.Load()\r\n   at NUnit.Engine.Runners.MasterTestRunner.LoadPackage()\r\n   at NUnit.Engine.Runners.AbstractTestRunner.EnsurePackageIsLoaded()\r\n   at NUnit.Engine.Runners.MasterTestRunner.NUnit.Engine.ITestRunner.Explore(TestFilter filter)\r\n\r\nMy calling code looks like this:\r\n\t\t\tusing (var engine = TestEngineActivator.CreateInstance(privateCopy: true))\r\n\t\t\tusing (var runner = engine.GetRunner(new TestPackage(path)))\r\n\t\t\t{\r\n\t\t\t\tvar xml = runner.Explore(TestFilter.Empty);\r\n\t\t\t}\r\n\r\nIt appears that this code writes to the Nunit30Settings.xml file every time it runs, thus creating the access error when one process is writing to the settings file and another is loading it.\r\n\r\nThe contents that are saved to the file are as follows:\r\n<?xml version=\"1.0\"?>\r\n<NUnitSettings>\r\n  <Settings />\r\n</NUnitSettings>"},"comment":{"url":"https://api.github.com/repos/nunit/nunit/issues/comments/184426242","html_url":"https://github.com/nunit/nunit/issues/1270#issuecomment-184426242","issue_url":"https://api.github.com/repos/nunit/nunit/issues/1270","id":184426242,"user":{"login":"CharliePoole","id":2678661,"avatar_url":"https://avatars.githubusercontent.com/u/2678661?v=3","gravatar_id":"","url":"https://api.github.com/users/CharliePoole","html_url":"https://github.com/CharliePoole","followers_url":"https://api.github.com/users/CharliePoole/followers","following_url":"https://api.github.com/users/CharliePoole/following{/other_user}","gists_url":"https://api.github.com/users/CharliePoole/gists{/gist_id}","starred_url":"https://api.github.com/users/CharliePoole/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CharliePoole/subscriptions","organizations_url":"https://api.github.com/users/CharliePoole/orgs","repos_url":"https://api.github.com/users/CharliePoole/repos","events_url":"https://api.github.com/users/CharliePoole/events{/privacy}","received_events_url":"https://api.github.com/users/CharliePoole/received_events","type":"User","site_admin":false},"created_at":"2016-02-15T22:38:50Z","updated_at":"2016-02-15T22:38:50Z","body":"I'll look at clarifying the docs, but actually that's not what I'm saying at all. It's the SettingsService that should only have one writable instance at a time. When you initialize an Engine, you give it a bunch of services, usually including a SettingsService. Its the SettingsService that can be writable or not.\r\n\r\nAgain, it's the SettingsService that, if it's writable, flushes its content to disk when the service is stopped. If it's not writable, it naturally doesn't do so. If you initialize your engine with a non-writable SettingsService in the first place, you won't have the problem at all.\r\n\r\n[SettingsService could, of course, check to see if anything is dirty before saving its content. But that would involve a bit of extra code that we decided to omit.]\r\n\r\nWhat you are doing sounds like something that NUnit could do as designed, using multiple Runners provided by a single engine rather than multiple (primary) engines. (As opposed to the second-level engines created by the nunit-agent program.) Just create a test package and get an ITestRunner for each job as it comes along. Using default settings in the package will give you process isolation and automatically select the target framework and bitness of the process to be used.\r\n\r\nHowever, if you are already invested in the approach you are taking, you should stop using the TestEngineActivator to create your engines. It is designed for \"mass market\" use and creates an engine with the services that are usually needed by almost all users. You should look at how the nunit-agent program creates and initializes the engine instead. It actually instantiates the TestEngine class and initializes it with a set of services that are needed in an agent runner.\r\n"}}