mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
another attempt to workaround a glibc bug
This is another attempt to fix issue #3644 that we believe is due to issue https://sourceware.org/bugzilla/show_bug.cgi?id=20632.
This commit is contained in:
parent
2e9a349dd0
commit
56e05dab02
3 changed files with 34 additions and 17 deletions
|
@ -1710,7 +1710,9 @@ void restore_term_foreground_process_group(void) {
|
|||
if (initial_fg_process_group != -1) {
|
||||
// This is called during shutdown and from a signal handler. We don't bother to complain on
|
||||
// failure.
|
||||
tcsetpgrp(STDIN_FILENO, initial_fg_process_group);
|
||||
if (tcsetpgrp(STDIN_FILENO, initial_fg_process_group) == -1 && errno == ENOTTY) {
|
||||
redirect_tty_output();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1943,13 +1945,13 @@ bool fish_reserved_codepoint(wchar_t c) {
|
|||
(c >= INPUT_COMMON_BASE && c < INPUT_COMMON_END);
|
||||
}
|
||||
|
||||
/// Reopen stdout and/or stderr on /dev/null. This is invoked when we find that our tty has become
|
||||
/// invalid.
|
||||
/// Reopen stdin, stdout and/or stderr on /dev/null. This is invoked when we find that our tty has
|
||||
/// become invalid.
|
||||
void redirect_tty_output() {
|
||||
struct termios t;
|
||||
int fd = open("/dev/null", O_WRONLY);
|
||||
if (tcgetattr(STDIN_FILENO, &t) == -1) dup2(fd, STDIN_FILENO);
|
||||
if (tcgetattr(STDOUT_FILENO, &t) == -1) dup2(fd, STDOUT_FILENO);
|
||||
if (tcgetattr(STDERR_FILENO, &t) == -1) dup2(fd, STDERR_FILENO);
|
||||
if (tcgetattr(STDIN_FILENO, &t) == -1 && errno == EIO) dup2(fd, STDIN_FILENO);
|
||||
if (tcgetattr(STDOUT_FILENO, &t) == -1 && errno == EIO) dup2(fd, STDOUT_FILENO);
|
||||
if (tcgetattr(STDERR_FILENO, &t) == -1 && errno == EIO) dup2(fd, STDERR_FILENO);
|
||||
close(fd);
|
||||
}
|
||||
|
|
|
@ -820,7 +820,7 @@ static int terminal_return_from_job(job_t *j) {
|
|||
|
||||
// Save jobs terminal modes.
|
||||
if (tcgetattr(STDIN_FILENO, &j->tmodes)) {
|
||||
if (errno == ENOTTY) redirect_tty_output();
|
||||
if (errno == EIO) redirect_tty_output();
|
||||
debug(1, _(L"Could not return shell to foreground"));
|
||||
wperror(L"tcgetattr");
|
||||
return 0;
|
||||
|
@ -832,7 +832,8 @@ static int terminal_return_from_job(job_t *j) {
|
|||
// https://github.com/fish-shell/fish-shell/issues/121
|
||||
#if 0
|
||||
// Restore the shell's terminal modes.
|
||||
if (tcsetattr(STDIN_FILENO, TCSADRAIN, &shell_modes)) {
|
||||
if (tcsetattr(STDIN_FILENO, TCSADRAIN, &shell_modes) == -1) {
|
||||
if (errno == EIO) redirect_tty_output();
|
||||
debug(1, _(L"Could not return shell to foreground"));
|
||||
wperror(L"tcsetattr");
|
||||
return 0;
|
||||
|
|
|
@ -318,7 +318,7 @@ static void term_donate() {
|
|||
|
||||
while (1) {
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &tty_modes_for_external_cmds) == -1) {
|
||||
if (errno == ENOTTY) redirect_tty_output();
|
||||
if (errno == EIO) redirect_tty_output();
|
||||
if (errno != EINTR) {
|
||||
debug(1, _(L"Could not set terminal mode for new job"));
|
||||
wperror(L"tcsetattr");
|
||||
|
@ -347,7 +347,7 @@ static void update_buff_pos(editable_line_t *el, size_t buff_pos) {
|
|||
static void term_steal() {
|
||||
while (1) {
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &shell_modes) == -1) {
|
||||
if (errno == ENOTTY) redirect_tty_output();
|
||||
if (errno == EIO) redirect_tty_output();
|
||||
if (errno != EINTR) {
|
||||
debug(1, _(L"Could not set terminal mode for shell"));
|
||||
perror("tcsetattr");
|
||||
|
@ -794,7 +794,7 @@ void restore_term_mode() {
|
|||
// Restore the term mode if we own the terminal. It's important we do this before
|
||||
// restore_foreground_process_group, otherwise we won't think we own the terminal.
|
||||
if (getpid() == tcgetpgrp(STDIN_FILENO)) {
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &terminal_mode_on_startup) == -1 && errno == ENOTTY) {
|
||||
if (tcsetattr(STDIN_FILENO, TCSANOW, &terminal_mode_on_startup) == -1 && errno == EIO) {
|
||||
redirect_tty_output();
|
||||
}
|
||||
}
|
||||
|
@ -1590,8 +1590,9 @@ static void reader_interactive_init() {
|
|||
for (unsigned long loop_count = 0;; loop_count++) {
|
||||
pid_t owner = tcgetpgrp(STDIN_FILENO);
|
||||
shell_pgid = getpgrp();
|
||||
if (owner < 0 && errno == ENOTTY) {
|
||||
if (owner == -1 && errno == ENOTTY) {
|
||||
// No TTY, cannot be interactive?
|
||||
redirect_tty_output();
|
||||
debug(1, _(L"No TTY for interactive shell (tcgetpgrp failed)"));
|
||||
wperror(L"setpgid");
|
||||
exit_without_destructors(1);
|
||||
|
@ -1643,7 +1644,7 @@ static void reader_interactive_init() {
|
|||
|
||||
// Set the new modes.
|
||||
if (tcsetattr(0, TCSANOW, &shell_modes) == -1) {
|
||||
if (errno == ENOTTY) redirect_tty_output();
|
||||
if (errno == EIO) redirect_tty_output();
|
||||
wperror(L"tcsetattr");
|
||||
}
|
||||
|
||||
|
@ -2383,10 +2384,10 @@ const wchar_t *reader_readline(int nchars) {
|
|||
reader_repaint();
|
||||
|
||||
// Get the current terminal modes. These will be restored when the function returns.
|
||||
tcgetattr(STDIN_FILENO, &old_modes);
|
||||
if (tcgetattr(STDIN_FILENO, &old_modes) == -1 && errno == EIO) redirect_tty_output();
|
||||
// Set the new modes.
|
||||
if (tcsetattr(0, TCSANOW, &shell_modes) == -1) {
|
||||
if (errno == ENOTTY) redirect_tty_output();
|
||||
if (errno == EIO) redirect_tty_output();
|
||||
wperror(L"tcsetattr");
|
||||
}
|
||||
|
||||
|
@ -3253,7 +3254,7 @@ const wchar_t *reader_readline(int nchars) {
|
|||
|
||||
if (!reader_exit_forced()) {
|
||||
if (tcsetattr(0, TCSANOW, &old_modes) == -1) {
|
||||
if (errno == ENOTTY) redirect_tty_output();
|
||||
if (errno == EIO) redirect_tty_output();
|
||||
wperror(L"tcsetattr"); // return to previous mode
|
||||
}
|
||||
set_color(rgb_color_t::reset(), rgb_color_t::reset());
|
||||
|
@ -3359,7 +3360,20 @@ int reader_read(int fd, const io_chain_t &io) {
|
|||
// If reader_read is called recursively through the '.' builtin, we need to preserve
|
||||
// is_interactive. This, and signal handler setup is handled by
|
||||
// proc_push_interactive/proc_pop_interactive.
|
||||
int inter = ((fd == STDIN_FILENO) && isatty(STDIN_FILENO));
|
||||
int inter = 0;
|
||||
// This block is a hack to work around https://sourceware.org/bugzilla/show_bug.cgi?id=20632.
|
||||
// See also, commit 396bf12. Without the need for this workaround we would just write:
|
||||
// int inter = ((fd == STDIN_FILENO) && isatty(STDIN_FILENO));
|
||||
if (fd == STDIN_FILENO) {
|
||||
struct termios t;
|
||||
int a_tty = isatty(STDIN_FILENO);
|
||||
if (a_tty) {
|
||||
inter = 1;
|
||||
} else if (tcgetattr(STDIN_FILENO, &t) == -1 && errno == EIO) {
|
||||
redirect_tty_output();
|
||||
inter = 1;
|
||||
}
|
||||
}
|
||||
proc_push_interactive(inter);
|
||||
|
||||
res = shell_is_interactive() ? read_i() : read_ni(fd, io);
|
||||
|
|
Loading…
Reference in a new issue