Skip to content

Fix encoding 866 crash: fallback to UTF-8 when console encoding unavailable - #365

Open
dronov-dmitry wants to merge 2 commits into
IronLanguages:mainfrom
dronov-dmitry:fix/encoding-866-clean
Open

dronov-dmitry wants to merge 2 commits into
IronLanguages:mainfrom
dronov-dmitry:fix/encoding-866-clean

Conversation

@dronov-dmitry

Copy link
Copy Markdown

Problem

SharedIO.InitializeInput() accesses Console.InputEncoding without error handling. On Russian Windows this returns cp866, but in hosting environments like Dynamo (Autodesk Revit) or on .NET Core, the codepage data is unavailable, causing:

ArgumentException: No data is available for encoding 866

This crashes Python.CreateEngine() in IronPython.

Fix

Added TryGetConsoleEncoding() helper that wraps console encoding access in try-catch with fallback:

private static Encoding TryGetConsoleEncoding(Func<Encoding> getter, Encoding fallback) {
    try { return getter(); } catch { return fallback; }
}

Applied to SupportLevel.Full case in:

  • InitializeInput() — Console.InputEncoding → fallback Encoding.UTF8
  • InitializeOutput() — Console.Out.Encoding → fallback Encoding.UTF8
  • InitializeErrorOutput() — Console.Error.Encoding → fallback Encoding.UTF8

Companion PR

This fix works together with IronLanguages/ironpython2#851 which adds Encoding.RegisterProvider(CodePagesEncodingProvider.Instance) in PythonContext static constructor for .NET Core/Standard.

Testing

Verified with C# host simulating Dynamo environment — all tests pass.

…coding unavailable

SharedIO.InitializeInput/Output/ErrorOutput accessed Console.InputEncoding
and Console.Out/Console.Error without error handling. On systems where cp866
(or other console encodings) are not registered (e.g. Dynamo/Revit hosting
environment, .NET Core), this threw ArgumentException:
  'No data is available for encoding 866'

Added TryGetConsoleEncoding() helper that wraps encoding access in try-catch
and falls back to Encoding.UTF8 / TextWriter.Null when the console encoding
is unavailable.
@dronov-dmitry

Copy link
Copy Markdown
Author

@dotnet-policy-service agree

The previous change guarded Console.InputEncoding/Console.Out.Encoding but
still failed in the situations it was meant to survive:

1. Console.In is built from Console.InputEncoding (see
   ConsolePal.GetOrCreateReader), so it threw again right after the guarded
   read and the engine still failed to start.
2. The output/error ternary evaluated Console.Out / Console.Error a second
   time outside the try, so the UTF-8 fallback re-entered the throwing
   getter and the exception escaped.
3. The replacement StreamWriter did not set AutoFlush, while Console.Out is
   created with AutoFlush = true, so output smaller than the 64 byte buffer
   was silently dropped.

Console.In / Console.Out / Console.Error are now each evaluated once inside
a guard, with readers/writers that keep stdin/stdout open, auto-flush and
fall back to UTF-8 (or TextReader.Null) when the console is unavailable. The
non UTF-16/UTF-8 writer replacement is gone: it provided no benefit and
dropped the synchronized wrapper Console.Out normally has.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant