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

Fix "Failed tcsetattr(TCSADRAIN)" when nix repl is not a TTY #10010

Merged
merged 1 commit into from
Feb 28, 2024

Conversation

9999years
Copy link
Contributor

Fixes #9941.

Before:

$ echo builtins.nixVersion | nix repl
Welcome to Nix 2.18.1. Type :? for help.

Failed tcsetattr(TCSADRAIN): Inappropriate ioctl for device
"2.18.1"

Failed tcsetattr(TCSADRAIN): Inappropriate ioctl for device

After:

$ echo builtins.nixVersion | nix repl
Nix 2.21.0pre20240131_dirty
Type :? for help.
"2.21.0pre20240131_dirty"

Before:
```
$ echo builtins.nixVersion | nix repl
Welcome to Nix 2.18.1. Type :? for help.

Failed tcsetattr(TCSADRAIN): Inappropriate ioctl for device
"2.18.1"

Failed tcsetattr(TCSADRAIN): Inappropriate ioctl for device
```

After:
```
$ echo builtins.nixVersion | nix repl
Nix 2.21.0pre20240131_dirty
Type :? for help.
"2.21.0pre20240131_dirty"
```
@9999years 9999years requested a review from edolstra as a code owner February 13, 2024 19:10
@github-actions github-actions bot added the repl The Read Eval Print Loop, "nix repl" command and debugger label Feb 13, 2024
@@ -351,7 +351,6 @@ bool NixRepl::getLine(std::string & input, const std::string & prompt)
};

setupSignals();
Finally resetTerminal([&]() { rl_deprep_terminal(); });
Copy link
Contributor Author

Choose a reason for hiding this comment

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

editline already calls rl_prep_terminal and rl_deprep_terminal in readline, so I'm not sure what the point of this was, especially since there's no matching rl_prep_terminal call.

It was added in #5665 without comment about what sort of "exceptional exits" can lead to the terminal not being reset or any tests.

Copy link
Member

Choose a reason for hiding this comment

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

I doubt I did #5665 for no reason, so I assume it was needed at the time. So if we remove this, we have to be sure that there are no exceptions that can leave the terminal in a raw state.

Copy link
Member

Choose a reason for hiding this comment

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

Can we test this assumption it is necessary by putting some code in there that throws an uncaught exception and see if it indeed fails to deinitialize the terminal?

Copy link
Contributor

Choose a reason for hiding this comment

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

in gnu readline also calls deprep automatically. we can't find anything in the readline history that would tell us why calling deprep manually should be necessary unless you're hooking into readline itself, which nix does not do.

Copy link
Member

Choose a reason for hiding this comment

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

What if a completer throws? (n.b. it is also probably bad to unwind through libreadline, which is c, in such an instance)

Copy link
Contributor

Choose a reason for hiding this comment

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

we'd consider a throwing completer a bug for the exact reason you mentioned. this kind of thing should be handled by wrappers that stash away the exception, return through the normal readline path, and rethrow it after readline has finished processing

@@ -351,7 +351,6 @@ bool NixRepl::getLine(std::string & input, const std::string & prompt)
};

setupSignals();
Finally resetTerminal([&]() { rl_deprep_terminal(); });
Copy link
Member

Choose a reason for hiding this comment

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

alternatively :)

    Finally resetTerminal([&]() { if (isatty(STDIN_FILENO) rl_deprep_terminal(); });

@thufschmitt thufschmitt merged commit 864fc85 into NixOS:master Feb 28, 2024
8 checks passed
tebowy pushed a commit to tebowy/nix that referenced this pull request Jul 11, 2024
Fix "Failed tcsetattr(TCSADRAIN)" when `nix repl` is not a TTY

(cherry picked from commit 864fc85)
Change-Id: I8198674b935fabd741a349cc74544e61c53ea7b3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
repl The Read Eval Print Loop, "nix repl" command and debugger
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

nix repl prints error messages when input is not a TTY
5 participants