Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#98441 - Ignore invalid handle/access when setting console cp #98641

Merged
merged 6 commits into from
Feb 22, 2024

Conversation

nick-beer
Copy link
Contributor

There are situations where setting the console code page is expected to fail. For instance, if the application was started with DETACHED_PROCESS, the attempting to set the code page will fail with ERROR_INVALID_HANDLE. In these cases, ignore the returned error.

Fixes #98441

There are situations where setting the console code page is expected to
fail. For instance, if the application was started with DETACHED_PROCESS,
the attempting to set the code page will fail with ERROR_INVALID_HANDLE.
In these cases, ignore the returned error.

Fix dotnet#98441
@ghost
Copy link

ghost commented Feb 18, 2024

Tagging subscribers to this area: @dotnet/area-system-console
See info in area-owners.md if you want to be subscribed.

Issue Details

There are situations where setting the console code page is expected to fail. For instance, if the application was started with DETACHED_PROCESS, the attempting to set the code page will fail with ERROR_INVALID_HANDLE. In these cases, ignore the returned error.

Fixes #98441

Author: nick-beer
Assignees: -
Labels:

area-System.Console

Milestone: -

@nick-beer
Copy link
Contributor Author

@dotnet-policy-service agree company="National Instruments"

@jkotas
Copy link
Member

jkotas commented Feb 19, 2024

Is it possible to add a test?

coding conventions: use explicit Type rather than var

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
This helps ensure GetLastError is called immediately after the failing
win32 function.
@jhudsoncedaron
Copy link

@jkotas : Yes, but only if the test is allowed to start a new project. I put a short crash sequence in the work item thread.

@nick-beer
Copy link
Contributor Author

nick-beer commented Feb 20, 2024

Yeah - I should have updated this thread. I'm currently working on a couple tests for this issue. It took a little bit of time to aquaint myself with the test infrastrucure. It looks to me like the existing RemoteExecutor infrastructure only uses Process.Start to run the external process, so it's not easy to start a detached process. I now have tests that use FreeConsole to simulate a similar scenario, but I'm getting unexpected results. Trying to debug the failures is resulting in Visual Studio crashes, so it's taking a little longer than I'd hoped.

Do we agree that tests with FreeConsole to simulate a detached console are valuable?

Edit: to be clear, the FreeConsole call happens within the context of a RemoteExecutor test - so it should not impact other tests.

@jkotas
Copy link
Member

jkotas commented Feb 20, 2024

Either FreeConsole or launching a process with DETACHED_PROCESS flags should work for a test.

If you would like to go with DETACHED_PROCESS, ProcessorCount_Windows_RespectsJobCpuRateAndConfigurationSetting has an example for how to launch child test process with custom Windows-specific settings.

@nick-beer
Copy link
Contributor Author

Tests added. I went with FreeConsole. I like the way the test you linked to re ran the process with custom flags - pretty cool.

// The internal state of Console should have updated, despite the failure to change the console's input encoding
Assert.Equal(encoding, Console.InputEncoding);
// Operations on the console are no longer valid - GetConsoleCP fails.
Assert.Equal(0u, GetConsoleCP());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would advise testing that Console.WriteLine() still works here. The caller would need to use StandardOutputRedirected = true for the test case.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thank you

@jkotas jkotas requested a review from adamsitnik February 20, 2024 21:56
@jkotas
Copy link
Member

jkotas commented Feb 20, 2024

The test is failing on Windows Nano Server:

Unhandled exception. Xunit.Sdk.NotEqualException: Assert.NotEqual() Failure: Values are equal
Expected: Not 65001
Actual:       65001
   at Xunit.Assert.NotEqual[T](T expected, T actual, IEqualityComparer`1 comparer) in /_/src/Microsoft.DotNet.XUnitAssert/src/EqualityAsserts.cs:line 696
   at Xunit.Assert.NotEqual[T](T expected, T actual) in /_/src/Microsoft.DotNet.XUnitAssert/src/EqualityAsserts.cs:line 610
   at ConsoleEncoding.<>c.<InputEncoding_SetEncodingWhenDetached_ErrorIsSilentlyIgnored>b__12_0() in /_/src/libraries/System.Console/tests/ConsoleEncoding.Windows.cs:line 48
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args) in /_/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.CoreCLR.cs:line 36
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr) in /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs:line 57
--- End of stack trace from previous location ---
   at Microsoft.DotNet.RemoteExecutor.Program.Main(String[] args) in /_/src/Microsoft.DotNet.RemoteExecutor/src/Program.cs:line 97
    ConsoleEncoding.InputEncoding_SetEncodingWhenDetached_ErrorIsSilentlyIgnored [FAIL]
      Microsoft.DotNet.RemoteExecutor.RemoteExecutionException : Remote process failed with an unhandled exception.
      Stack Trace:
        
        Child exception:
          Xunit.Sdk.NotEqualException: Assert.NotEqual() Failure: Values are equal
        Expected: Not 65001
        Actual:       65001
        /_/src/libraries/System.Console/tests/ConsoleEncoding.Windows.cs(48,0): at ConsoleEncoding.<>c.<InputEncoding_SetEncodingWhenDetached_ErrorIsSilentlyIgnored>b__12_0()
           at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
        /_/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.CoreCLR.cs(36,0): at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
        /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs(57,0): at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
        
        Child process:
          System.Console.Tests, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 ConsoleEncoding+<>c Void <InputEncoding_SetEncodingWhenDetached_ErrorIsSilentlyIgnored>b__12_0()

@jhudsoncedaron
Copy link

I see why the test is failing. The code asserts that the current output codepage is not the one it's going to try to test by changing it to. So the test knows it doesn't work and bails.

Looks like the test harness needs to handle that case. Clearly the implementation needs to be if already 65001 use some other codepage instead of 65001. I'm not sure which code page it should change to though. Code page 437 would be a sane choice everywhere else but I'm not sure about nano.

@jkotas
Copy link
Member

jkotas commented Feb 20, 2024

Any one of the built-in .NET encodings should work:

case CodePageDefault: return Default; // 0
case CodePageUnicode: return Unicode; // 1200
case CodePageBigEndian: return BigEndianUnicode; // 1201
case CodePageUTF32: return UTF32; // 12000
case CodePageUTF32BE: return BigEndianUTF32; // 12001
case CodePageUTF8: return UTF8; // 65001
case CodePageASCII: return ASCII; // 20127
case ISO_8859_1: return Latin1; // 28591

@nick-beer
Copy link
Contributor Author

Updated to ensure we set an encoding that's different from whatever is existing. Also updated two existing tests that were not performing such a check.

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you @nick-beer for providing not just the fix but also great tests!

@adamsitnik adamsitnik merged commit 831ca1e into dotnet:main Feb 22, 2024
104 of 111 checks passed
@adamsitnik adamsitnik added this to the 9.0.0 milestone Feb 22, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Mar 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

dotnet CLI commands no longer work in .NET 7/8 with detached console
5 participants