arcade: RemoteExecutor Swallows Errors and Throws Invalid Exceptions
- This issue is blocking
- This issue is causing unreasonable pain
I could be holding it wrong but it does not seem to be working as expected.
Microsoft.DotNet.RemoteExecutor Version 6.0.0-beta.20508.3 (Are there non beta version available?)
Installed via https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json
The following method runs without any assertation exceptions. I would expect it to fail.
RemoteExecutor.Invoke(() =>
{
Assert.True(false);
}).Dispose();
The following code throws an exception. I would expect none.
RemoteExecutor.Invoke(() =>
{
return RemoteExecutor.SuccessExitCode;
}).Dispose();
Message: Exit code was -2147450749 but it should have been 42 Expected: True Actual: False Stack Trace: RemoteInvokeHandle.Dispose(Boolean disposing) line 237 RemoteInvokeHandle.Dispose() line 58
About this issue
- Original URL
- State: open
- Created 4 years ago
- Comments: 43 (29 by maintainers)
Thanks for reporting @JimBobSquarePants and @vitek-karas for the analysis. Vitek is right that RemoteExecutor doesn’t set
HostRunner(the path to the host to invoke) to the right value in cases where VSTest’s apphost is used. This didn’t show up for us in dotnet/runtime as we don’t use VSTest’s apphost feature as we supply our custom host.As a simple fallback mechanism we could check if processFileName ends with (dotnet[.exe]) and if not, use the dotnet in the %PATH%.
For a more complete implementation, we should follow what Vitek proposes:
An implementation of that could look like this:
dotnethost is found.@vitek-karas do you think we should stop at some point climbing up the directory tree? For self-contained application we need to fallback to %PATH% as a self-contained application doesn’t have a dotnet host. Right?
Thanks - I was able to repro it locally.
The command line it executes doesn’t seem to make sense to me:
This would work if it were running “dotnet.exe exec …”, but I doubt testhost recognizes “exec” (I could be wrong though).
In any case the command line won’t work because the special host parameters must be first on the command line:
--runtimeconfigand so on. Sincetesthost.exeis an apphost it doesn’t inherently recognizeexecon the host level, and so it runs itself as if there were no special parameters on the command line. And thus it tries to read the filetesthost.runtimeconfig.jsonwhich doesn’t exist (thevalid=[1]is misleading, internally the host treats missing runtime config as valid) - so it ends up with empty runtime config which means no framework references and thus tries to run as self-contained - which it’s not and so on.I tried running the same command line via
dotnet.exe execand that works (well at least it runs the code).I don’t know how this passes tests (if they run) in Arcade repo and/or how it’s used in a case where it would actually work. But as is, this seems completely broken.
Also - I which we could update the
testhost.exeto some “recent” version, it’s 2.1 (I know we probably need it to be able to run 2.1 tests, unfortunately). In this case it means that the tracing from the testhost.exe is not visible in the trace file since it doesn’t recognizeCOREHOST_TRACEFILEwhich was added in 3.0.I think somebody from Arcade should comment on what is the intended command line. I can definitely help with figuring out what it should be in reality to get all the desired behaviors.
Couple of notes about what I think it SHOULD be doing:
testhost.exewon’t work because that is the VS test host runner, it does not support running the executor dll as a command line appdotnet.exe- but this will be tricky because it will need to pick the right one. The best way would probably be to use location of the runtime running the test (this will be tricky to get completely right with single-file, but it’s possible).The break was probably introduced by changes to the VSTest platform - some time ago it switched from running the test via “dotnet.exe” to using the “testhost.exe”. But that’s been quite a while now if I remember correctly.
100% agreed. Even though it’s an open source project, there is no support policy attached to it. When I ported this library over from CoreFx couple years ago, I only did so to share the implementation with ML.NET, aspnetcore and later winforms. We try our best to resolve reported issues but RemoteExecutor was never intended to support every possible variant like single file applications, mobile, etc. As an example I removed the UWP support as well as we stopped testing it in CoreFx’s main branch.
Haha, if only I read the test log 😃 But to be fair, this is a developer-centric error message, which is to a user (in this instance me or @JimBobSquarePants) carries little value, because there’s nothing the user can do to address the issue besides coming here and raise an issue.
This approach shifts the onus of bootstrapping to the consumer of the RE. Whilst this may fair to suggest this direction for custom scenarios you’ll need to convince me why running a test with the RE from under VS is not a mainstream scenario.
I don’t have any problem with a partial fix.
I’m curious: In your comment you mention that it makes your coverage unreliable. Does it mean that it fails only sometimes, or that you have to avoid running certain configurations entirely because of this?
I just started to work on a minimalistic fix before @RussKie commented. There are more and more PR-s in ImageSharp with out-of-process tests, and our coverage became very unreliable. We need a fix ASAP. I don’t have the time and the knowledge for a full-scale solution using startup hooks.
I believe the most urgent thing is to get this fixed for the common Windows cases as simply and as quickly as possible. (Climb up to find
dotnet.exe, keep originalHostRunnerif it’s not present.) This would unblock ImageSharp, and hopefully also @RussKie, without side effects on more exotic cases, and does not conflict with a future reimplementation with startup hooks. @vitek-karas will you accept such a PR?Alternative idea: Remove
readonlymodifier fromHostRunner, so users can configure it as needed.It’s an environment variable read by the host - hostfxr.dll, I think (this isn’t my area). So you should be able to set it anywhere eg before launching dotnet test, or in your test just before launching the remote executor.