Repository: dotnet/runtime
File: src/libraries/System.Console/src/System/ConsolePal.Unix.cs (C#)

Code before:
        // with an interactive terminal.  In that case, performance isn't critical
        // and we can use a smaller buffer to minimize working set.
        private const int InteractiveBufferSize = 255;

        // For performance we cache Cursor{Left,Top} and Window{Width,Height}.
        // These values must be read/written under lock (Console.Out).
        // We also need to invalidate these values when certain signals occur.
        // We don't want to take the lock in the signal handling thread for this.
        // Instead, we set a flag. Before reading a cached value, a call to CheckTerminalSettingsInvalidated
        // will invalidate the cached values if a signal has occurred.
        private static int s_cursorVersion; // Gets incremented each time the cursor position changed.
                                            // Used to synchronize between lock (Console.Out) blocks.
        private static int s_cursorLeft;    // Cached CursorLeft, -1 when invalid.
        private static int s_cursorTop;     // Cached CursorTop, invalid when s_cursorLeft == -1.
        private static int s_windowWidth;   // Cached WindowWidth, -1 when invalid.
        private static int s_windowHeight;  // Cached WindowHeight, invalid when s_windowWidth == -1.
        private static int s_invalidateCachedSettings = 1; // Tracks whether we should invalidate the cached settings.
        private static SafeFileHandle? s_terminalHandle; // Tracks the handle used for writing to the terminal.

        /// <summary>Gets the lazily-initialized terminal information for the terminal.</summary>
        public static TerminalFormatStrings TerminalFormatStringsInstance { get { return s_terminalFormatStringsInstance.Value; } }
        private static readonly Lazy<TerminalFormatStrings> s_terminalFormatStringsInstance = new(() => new TerminalFormatStrings(TermInfo.DatabaseFactory.ReadActiveDatabase()));

        public static Stream OpenStandardInput()
        {
            return new UnixConsoleStream(OpenStandardInputHandle(verifyFd: false), FileAccess.Read,
                                         useReadLine: !Console.IsInputRedirected);
        }

        public static Stream OpenStandardOutput()
        {
            return new UnixConsoleStream(OpenStandardOutputHandle(verifyFd: false), FileAccess.Write);
        }

        public static Stream OpenStandardError()
        {
            return new UnixConsoleStream(OpenStandardErrorHandle(verifyFd: false), FileAccess.Write);
        }

        public static SafeFileHandle OpenStandardInputHandle(bool verifyFd = true) => OpenStandardHandle(0, FileAccess.Read, verifyFd);

        public static SafeFileHandle OpenStandardOutputHandle(bool verifyFd = true) => OpenStandardHandle(1, FileAccess.Write, verifyFd);

        public static SafeFileHandle OpenStandardErrorHandle(bool verifyFd = true) => OpenStandardHandle(2, FileAccess.Write, verifyFd);

        private static SafeFileHandle OpenStandardHandle(IntPtr fd, FileAccess access, bool verifyFd)
        {
            if (verifyFd)
            {
                Interop.CheckIo(Interop.Sys.Fcntl.CheckAccess(fd, (int)access));
            }

Review comment (suggestion):
We were using `Interop.CheckIo(Interop.Sys.Dup` here, which would have thrown. Let's keep doing that.

```suggestion
            return new UnixConsoleStream(OpenStandardInputHandle(), FileAccess.Read,
```

Code after:
        // with an interactive terminal.  In that case, performance isn't critical
        // and we can use a smaller buffer to minimize working set.
        private const int InteractiveBufferSize = 255;

        // For performance we cache Cursor{Left,Top} and Window{Width,Height}.
        // These values must be read/written under lock (Console.Out).
        // We also need to invalidate these values when certain signals occur.
        // We don't want to take the lock in the signal handling thread for this.
        // Instead, we set a flag. Before reading a cached value, a call to CheckTerminalSettingsInvalidated
        // will invalidate the cached values if a signal has occurred.
        private static int s_cursorVersion; // Gets incremented each time the cursor position changed.
                                            // Used to synchronize between lock (Console.Out) blocks.
        private static int s_cursorLeft;    // Cached CursorLeft, -1 when invalid.
        private static int s_cursorTop;     // Cached CursorTop, invalid when s_cursorLeft == -1.
        private static int s_windowWidth;   // Cached WindowWidth, -1 when invalid.
        private static int s_windowHeight;  // Cached WindowHeight, invalid when s_windowWidth == -1.
        private static int s_invalidateCachedSettings = 1; // Tracks whether we should invalidate the cached settings.
        private static SafeFileHandle? s_terminalHandle; // Tracks the handle used for writing to the terminal.

        /// <summary>Gets the lazily-initialized terminal information for the terminal.</summary>
        public static TerminalFormatStrings TerminalFormatStringsInstance { get { return s_terminalFormatStringsInstance.Value; } }
        private static readonly Lazy<TerminalFormatStrings> s_terminalFormatStringsInstance = new(() => new TerminalFormatStrings(TermInfo.DatabaseFactory.ReadActiveDatabase()));

        public static Stream OpenStandardInput()
        {
            return new UnixConsoleStream(OpenStandardInputHandle(), FileAccess.Read,
                                         useReadLine: !Console.IsInputRedirected);
        }

        public static Stream OpenStandardOutput()
        {
            return new UnixConsoleStream(OpenStandardOutputHandle(), FileAccess.Write);
        }

        public static Stream OpenStandardError()
        {
            return new UnixConsoleStream(OpenStandardErrorHandle(), FileAccess.Write);
        }

        public static SafeFileHandle OpenStandardInputHandle() => OpenStandardHandle(0);

        public static SafeFileHandle OpenStandardOutputHandle() => OpenStandardHandle(1);

        public static SafeFileHandle OpenStandardErrorHandle() => OpenStandardHandle(2);

        private static SafeFileHandle OpenStandardHandle(IntPtr fd) => new SafeFileHandle(fd, ownsHandle: false);

        public static Encoding InputEncoding
        {
            get { return GetConsoleEncoding(); }
        }