public override void InitStreams(LaunchOptions options, out StreamReader reader, out StreamWriter writer)
        {
            LocalLaunchOptions localOptions = (LocalLaunchOptions)options;

            // Default working directory is next to the app
            string debuggeeDir;

            if (Path.IsPathRooted(options.ExePath) && File.Exists(options.ExePath))
            {
                debuggeeDir = Path.GetDirectoryName(options.ExePath);
            }
            else
            {
                // If we don't know where the app is, default to HOME, and if we somehow can't get that, go with the root directory.
                debuggeeDir = Environment.GetEnvironmentVariable("HOME");
                if (string.IsNullOrEmpty(debuggeeDir))
                {
                    debuggeeDir = "/";
                }
            }

            _dbgStdInName  = UnixUtilities.MakeFifo(Logger);
            _dbgStdOutName = UnixUtilities.MakeFifo(Logger);
            string pidFifo = UnixUtilities.MakeFifo(Logger);

            // Used for testing
            Logger?.WriteLine(string.Concat("TempFile=", _dbgStdInName));
            Logger?.WriteLine(string.Concat("TempFile=", _dbgStdOutName));
            Logger?.WriteLine(string.Concat("TempFile=", pidFifo));

            // Setup the streams on the fifos as soon as possible.
            FileStream dbgStdInStream  = new FileStream(_dbgStdInName, FileMode.Open);
            FileStream dbgStdOutStream = new FileStream(_dbgStdOutName, FileMode.Open);
            FileStream pidStream       = new FileStream(pidFifo, FileMode.Open);

            string debuggerCmd           = UnixUtilities.GetDebuggerCommand(localOptions);
            string launchDebuggerCommand = UnixUtilities.LaunchLocalDebuggerCommand(
                debuggeeDir,
                _dbgStdInName,
                _dbgStdOutName,
                pidFifo,
                debuggerCmd);

            // Only pass the environment to launch clrdbg. For other modes, there are commands that set the environment variables
            // directly for the debuggee.
            ReadOnlyCollection <EnvironmentEntry> environmentForDebugger = localOptions.DebuggerMIMode == MIMode.Clrdbg ?
                                                                           localOptions.Environment :
                                                                           new ReadOnlyCollection <EnvironmentEntry>(new EnvironmentEntry[] { });;

            TerminalLauncher terminal = TerminalLauncher.MakeTerminal("DebuggerTerminal", launchDebuggerCommand, localOptions.Environment);

            terminal.Launch(debuggeeDir);

            int shellPid = -1;

            using (StreamReader pidReader = new StreamReader(pidStream, Encoding.UTF8, true, UnixUtilities.StreamBufferSize))
            {
                Task <string> readShellPidTask = pidReader.ReadLineAsync();
                if (readShellPidTask.Wait(TimeSpan.FromSeconds(10)))
                {
                    shellPid = int.Parse(readShellPidTask.Result, CultureInfo.InvariantCulture);
                    // Used for testing
                    Logger?.WriteLine(string.Concat("ShellPid=", shellPid));
                }
                else
                {
                    // Something is wrong because we didn't get the pid of shell
                    ForceDisposeStreamReader(pidReader);
                    Close();
                    throw new TimeoutException(MICoreResources.Error_LocalUnixTerminalDebuggerInitializationFailed);
                }

                _shellProcessMonitor = new ProcessMonitor(shellPid);
                _shellProcessMonitor.ProcessExited += ShellExited;
                _shellProcessMonitor.Start();

                Task <string> readDebuggerPidTask = pidReader.ReadLineAsync();
                try
                {
                    readDebuggerPidTask.Wait(_streamReadPidCancellationTokenSource.Token);
                    _debuggerPid = int.Parse(readDebuggerPidTask.Result, CultureInfo.InvariantCulture);
                }
                catch (OperationCanceledException)
                {
                    // Something is wrong because we didn't get the pid of the debugger
                    ForceDisposeStreamReader(pidReader);
                    Close();
                    throw new OperationCanceledException(MICoreResources.Error_LocalUnixTerminalDebuggerInitializationFailed);
                }
            }

            // The in/out names are confusing in this case as they are relative to gdb.
            // What that means is the names are backwards wrt miengine hence the reader
            // being the writer and vice-versa
            // Mono seems to hang when the debugger sends a large response unless we specify a larger buffer here
            writer = new StreamWriter(dbgStdInStream, new UTF8Encoding(false, true), UnixUtilities.StreamBufferSize);
            reader = new StreamReader(dbgStdOutStream, Encoding.UTF8, true, UnixUtilities.StreamBufferSize);
        }
        public override void InitStreams(LaunchOptions options, out StreamReader reader, out StreamWriter writer)
        {
            LocalLaunchOptions localOptions = (LocalLaunchOptions)options;

            // Default working directory is next to the app
            string debuggeeDir;
            if (Path.IsPathRooted(options.ExePath) && File.Exists(options.ExePath))
            {
                debuggeeDir = Path.GetDirectoryName(options.ExePath);
            }
            else
            {
                // If we don't know where the app is, default to HOME, and if we somehow can't get that, go with the root directory.
                debuggeeDir = Environment.GetEnvironmentVariable("HOME");
                if (string.IsNullOrEmpty(debuggeeDir))
                    debuggeeDir = "/";
            }

            _dbgStdInName = UnixUtilities.MakeFifo(Logger);
            _dbgStdOutName = UnixUtilities.MakeFifo(Logger);
            string pidFifo = UnixUtilities.MakeFifo(Logger);

            // Used for testing
            Logger?.WriteLine(string.Concat("TempFile=", _dbgStdInName));
            Logger?.WriteLine(string.Concat("TempFile=", _dbgStdOutName));
            Logger?.WriteLine(string.Concat("TempFile=", pidFifo));

            // Setup the streams on the fifos as soon as possible.
            FileStream dbgStdInStream = new FileStream(_dbgStdInName, FileMode.Open);
            FileStream dbgStdOutStream = new FileStream(_dbgStdOutName, FileMode.Open);
            FileStream pidStream = new FileStream(pidFifo, FileMode.Open);

            string debuggerCmd = UnixUtilities.GetDebuggerCommand(localOptions);
            string launchDebuggerCommand = UnixUtilities.LaunchLocalDebuggerCommand(
                debuggeeDir,
                _dbgStdInName,
                _dbgStdOutName,
                pidFifo,
                debuggerCmd);

            TerminalLauncher terminal = TerminalLauncher.MakeTerminal("DebuggerTerminal", launchDebuggerCommand, localOptions.Environment);
            terminal.Launch(debuggeeDir);

            int shellPid = -1;

            using (StreamReader pidReader = new StreamReader(pidStream, Encoding.UTF8, true, UnixUtilities.StreamBufferSize))
            {
                Task<string> readShellPidTask = pidReader.ReadLineAsync();
                if (readShellPidTask.Wait(TimeSpan.FromSeconds(10)))
                {
                    shellPid = int.Parse(readShellPidTask.Result, CultureInfo.InvariantCulture);
                    // Used for testing
                    Logger?.WriteLine(string.Concat("ShellPid=", shellPid));
                }
                else
                {
                    // Something is wrong because we didn't get the pid of shell
                    ForceDisposeStreamReader(pidReader);
                    Close();
                    throw new TimeoutException(MICoreResources.Error_LocalUnixTerminalDebuggerInitializationFailed);
                }

                _shellProcessMonitor = new ProcessMonitor(shellPid);
                _shellProcessMonitor.ProcessExited += ShellExited;
                _shellProcessMonitor.Start();

                Task<string> readDebuggerPidTask = pidReader.ReadLineAsync();
                try
                {
                    readDebuggerPidTask.Wait(_streamReadPidCancellationTokenSource.Token);
                    _debuggerPid = int.Parse(readDebuggerPidTask.Result, CultureInfo.InvariantCulture);
                }
                catch (OperationCanceledException)
                {
                    // Something is wrong because we didn't get the pid of the debugger
                    ForceDisposeStreamReader(pidReader);
                    Close();
                    throw new OperationCanceledException(MICoreResources.Error_LocalUnixTerminalDebuggerInitializationFailed);
                }
            }

            // The in/out names are confusing in this case as they are relative to gdb.
            // What that means is the names are backwards wrt miengine hence the reader
            // being the writer and vice-versa
            // Mono seems to hang when the debugger sends a large response unless we specify a larger buffer here
            writer = new StreamWriter(dbgStdInStream, new UTF8Encoding(false, true), UnixUtilities.StreamBufferSize);
            reader = new StreamReader(dbgStdOutStream, Encoding.UTF8, true, UnixUtilities.StreamBufferSize);
        }