Skip to content

Commit 5d4d55d

Browse files
committed
Revert "Merge pull request #13 from nickprotop/feat/terminal-resilience-non-interactive"
This reverts commit ab49e61, reversing changes made to ab8a504.
1 parent ab49e61 commit 5d4d55d

5 files changed

Lines changed: 7 additions & 210 deletions

File tree

SharpConsoleUI/Configuration/SystemDefaults.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,5 @@ public static class SystemDefaults
4545
/// Last Alt+Number window switch key (default: Alt+9)
4646
/// </summary>
4747
public const ConsoleKey LastWindowSwitchKey = ConsoleKey.D9;
48-
49-
// Terminal initialization
50-
/// <summary>
51-
/// Per-byte timeout in milliseconds for DSR terminal verification during startup.
52-
/// ReadDSRColumn calls readByte up to ~8 times, so effective worst-case timeout
53-
/// is ~8x this value (~4s at 500ms). Longer than the 150ms VS16 probe timeout
54-
/// because this is a one-time startup check and some embedded terminals may
55-
/// have higher latency.
56-
/// </summary>
57-
public const int TerminalVerificationTimeoutMs = 500;
5848
}
5949
}

SharpConsoleUI/Drivers/Input/TerminalRawMode.cs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -160,29 +160,6 @@ private struct PollFd
160160
[DllImport("libc", SetLastError = true)]
161161
private static extern int poll(ref PollFd fds, int nfds, int timeout);
162162

163-
[DllImport("libc")]
164-
private static extern int isatty(int fd);
165-
166-
/// <summary>
167-
/// Checks whether stdin (fd 0) and stdout (fd 1) are connected to a TTY.
168-
/// Returns false for either if piped or redirected.
169-
/// Always returns (true, true) on Windows.
170-
/// </summary>
171-
public static (bool stdinIsTty, bool stdoutIsTty) CheckTtyStatus()
172-
{
173-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
174-
return (true, true);
175-
176-
try
177-
{
178-
return (isatty(StdinFd) == 1, isatty(StdoutFd) == 1);
179-
}
180-
catch
181-
{
182-
return (false, false);
183-
}
184-
}
185-
186163
/// <summary>
187164
/// Reads a single byte from stdin with a timeout using poll() + read().
188165
/// Returns -1 on timeout or error. This is the correct way to do

SharpConsoleUI/Drivers/NetConsoleDriver.cs

Lines changed: 7 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
// License: MIT
77
// -----------------------------------------------------------------------
88

9-
using SharpConsoleUI.Configuration;
109
using SharpConsoleUI.Drivers.Input;
1110
using SharpConsoleUI.Helpers;
1211
using SharpConsoleUI.Themes;
@@ -343,44 +342,6 @@ public void Start()
343342
bool isUnix = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
344343
_useDirectAnsi = isUnix;
345344

346-
// Fail fast if stdin or stdout is not a TTY (piped/redirected)
347-
if (isUnix)
348-
{
349-
var (stdinIsTty, stdoutIsTty) = TerminalRawMode.CheckTtyStatus();
350-
351-
if (!stdinIsTty || !stdoutIsTty)
352-
{
353-
// Restore signals suppressed in constructor so caller's terminal works
354-
RestoreUnixSignal(SigInt);
355-
RestoreUnixSignal(SigTstp);
356-
if (_processExitHandler != null)
357-
{
358-
AppDomain.CurrentDomain.ProcessExit -= _processExitHandler;
359-
_processExitHandler = null;
360-
}
361-
362-
var term = Environment.GetEnvironmentVariable("TERM") ?? "(unset)";
363-
var details = new StringBuilder();
364-
details.AppendLine("SharpConsoleUI cannot start: interactive terminal required.");
365-
details.AppendLine();
366-
details.AppendLine("Current environment:");
367-
details.AppendLine($" TERM = {term}");
368-
details.AppendLine($" stdin is TTY: {stdinIsTty}");
369-
details.AppendLine($" stdout is TTY: {stdoutIsTty}");
370-
details.AppendLine();
371-
if (!stdinIsTty)
372-
details.AppendLine("Problem: stdin is not connected to a terminal (it appears to be piped or redirected).");
373-
if (!stdoutIsTty)
374-
details.AppendLine("Problem: stdout is not connected to a terminal (it appears to be piped or redirected).");
375-
details.AppendLine();
376-
details.AppendLine("How to fix:");
377-
details.AppendLine(" - Run the application directly in a terminal emulator (e.g., Terminal, iTerm2, Alacritty, Windows Terminal)");
378-
details.AppendLine(" - Do not pipe input/output (avoid: echo | app, app | cat, app > file)");
379-
details.AppendLine(" - If using an IDE, run in the integrated terminal, not as a background process");
380-
throw new TerminalNotSupportedException(details.ToString());
381-
}
382-
}
383-
384345
// Enter raw mode before creating console buffer (so ioctl is available)
385346
if (_useDirectAnsi)
386347
{
@@ -446,52 +407,6 @@ public void Start()
446407
// Uses DSR cursor position query to measure actual emoji width.
447408
ProbeTerminalCapabilities();
448409

449-
// Mandatory terminal verification: ensure terminal responds to escape sequences.
450-
// ProbeTerminalCapabilities (above) swallows failures — this is a hard check.
451-
if (_useDirectAnsi)
452-
{
453-
TerminalRawMode.FlushStdin();
454-
455-
bool responds = TerminalCapabilities.VerifyTerminalResponds(
456-
write: text => TerminalRawMode.WriteStdout(text),
457-
readByte: () => TerminalRawMode.ReadByteWithTimeout(
458-
SystemDefaults.TerminalVerificationTimeoutMs));
459-
460-
if (!responds)
461-
{
462-
var term = Environment.GetEnvironmentVariable("TERM") ?? "(unset)";
463-
_consoleWindowSystem?.LogService?.Log(
464-
Logging.LogLevel.Error,
465-
$"Terminal (TERM={term}) did not respond to DSR verification query. " +
466-
"Emergency exit: Ctrl+\\ (SIGQUIT).",
467-
"System");
468-
469-
// Roll back: Stop() handles partial initialization (Task 5 guards)
470-
Stop();
471-
472-
var details = new StringBuilder();
473-
details.AppendLine("SharpConsoleUI cannot start: terminal is not responding to escape sequences.");
474-
details.AppendLine();
475-
details.AppendLine("Current environment:");
476-
details.AppendLine($" TERM = {term}");
477-
details.AppendLine($" Verification: sent DSR query (ESC[6n), no response within {SystemDefaults.TerminalVerificationTimeoutMs}ms");
478-
details.AppendLine();
479-
details.AppendLine("This means the terminal is not processing ANSI escape sequences, which are");
480-
details.AppendLine("required for rendering the UI. The alternate screen buffer likely did not activate.");
481-
details.AppendLine();
482-
details.AppendLine("Common causes:");
483-
details.AppendLine(" - Embedded terminal that does not fully support ANSI (e.g., some IDE terminals)");
484-
details.AppendLine(" - Terminal multiplexer misconfiguration (tmux, screen)");
485-
details.AppendLine(" - TERM environment variable set incorrectly");
486-
details.AppendLine();
487-
details.AppendLine("How to fix:");
488-
details.AppendLine(" - Run in a standard terminal emulator (Terminal, iTerm2, Alacritty, Windows Terminal)");
489-
details.AppendLine(" - Ensure TERM is set correctly (e.g., xterm-256color)");
490-
details.AppendLine(" - If stuck, press Ctrl+\\ (SIGQUIT) to force exit");
491-
throw new TerminalNotSupportedException(details.ToString());
492-
}
493-
}
494-
495410
_lastConsoleWidth = screenSize.Width;
496411
_lastConsoleHeight = screenSize.Height;
497412

@@ -618,20 +533,15 @@ public void Stop()
618533
Console.Error.Flush();
619534
}
620535

621-
// Post-restore Console calls — may fail if Start() partially completed
622-
try
623-
{
624-
Console.Out.Write(cleanupSequence);
625-
Console.Out.Flush();
626-
Console.ResetColor();
627-
}
628-
catch { }
536+
Console.Out.Write(cleanupSequence);
537+
Console.Out.Flush();
538+
Console.ResetColor();
629539

630540
Thread.Sleep(50);
631541

632542
Cleanup();
633543

634-
try { Console.Clear(); } catch { }
544+
Console.Clear();
635545

636546
// Restore cursor visibility on shutdown
637547
SetCursorVisible(true);
@@ -954,21 +864,12 @@ private void ProbeTerminalCapabilities()
954864
private static extern bool SetConsoleMode(nint hConsoleHandle, uint dwMode);
955865

956866
// Unix signal constants for direct suppression via libc signal()
957-
// SIGINT (2, Ctrl+C) and SIGTSTP (20, Ctrl+Z) are suppressed to prevent
958-
// accidental interruption of the UI.
959-
// SIGQUIT (3, Ctrl+\) is intentionally NOT suppressed — it serves as
960-
// an emergency exit when the application is stuck.
961-
private const int SigInt = 2; // Ctrl+C — suppressed
962-
private const int SigTstp = 20; // Ctrl+Z — suppressed
867+
private const int SigInt = 2; // Ctrl+C
868+
private const int SigTstp = 20; // Ctrl+Z
963869

964870
private static void SuppressUnixSignal(int signum)
965871
{
966-
try { _unixSignal(signum, new IntPtr(1)); } catch { } // SIG_IGN = 1
967-
}
968-
969-
private static void RestoreUnixSignal(int signum)
970-
{
971-
try { _unixSignal(signum, IntPtr.Zero); } catch { } // SIG_DFL = 0
872+
try { _unixSignal(signum, new IntPtr(1)); } catch { }
972873
}
973874

974875
[DllImport("libc", EntryPoint = "signal")]

SharpConsoleUI/Drivers/TerminalNotSupportedException.cs

Lines changed: 0 additions & 49 deletions
This file was deleted.

SharpConsoleUI/Helpers/TerminalCapabilities.cs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,28 +64,6 @@ internal static void Reset()
6464
_supportsVS16Widening = null;
6565
}
6666

67-
/// <summary>
68-
/// Verifies the terminal responds to a DSR (Device Status Report) query.
69-
/// Unlike <see cref="Probe"/> which swallows failures, this returns false
70-
/// on timeout — indicating the terminal is not processing escape sequences.
71-
/// </summary>
72-
/// <param name="write">Action to write escape sequences to the terminal.</param>
73-
/// <param name="readByte">Function to read a single byte with timeout. Returns -1 on timeout.</param>
74-
/// <returns>True if the terminal responded, false if it timed out.</returns>
75-
public static bool VerifyTerminalResponds(Action<string> write, Func<int> readByte)
76-
{
77-
try
78-
{
79-
write("\x1b[6n");
80-
int col = ReadDSRColumn(readByte);
81-
return col >= 0;
82-
}
83-
catch
84-
{
85-
return false;
86-
}
87-
}
88-
8967
private static bool ProbeVS16(Action<string> write, Func<int> readByte)
9068
{
9169
// Strategy:

0 commit comments

Comments
 (0)