From 89f59bb12bec8a50dc7520e7784d79baba89b140 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Fri, 30 Nov 2012 10:01:51 +0400 Subject: [PATCH] Optimization of SIGWINCH handling. Signed-off-by: Andrew Borodin --- lib/tty/tty-ncurses.c | 39 ++++++++++++++++++++++++++++++++++++++ lib/tty/tty-slang.c | 34 ++++++++++++++++++++------------- lib/tty/tty.c | 32 ------------------------------- lib/widget/dialog-switch.c | 30 ++++------------------------- src/execute.c | 15 ++++++++++++++- src/subshell.c | 26 ++++++++++++++++--------- 6 files changed, 95 insertions(+), 81 deletions(-) diff --git a/lib/tty/tty-ncurses.c b/lib/tty/tty-ncurses.c index fe2d4cca0..ef92ceb4f 100644 --- a/lib/tty/tty-ncurses.c +++ b/lib/tty/tty-ncurses.c @@ -34,6 +34,10 @@ #include #include #include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#include #include "lib/global.h" #include "lib/strutil.h" /* str_term_form */ @@ -217,6 +221,41 @@ tty_shutdown (void) /* --------------------------------------------------------------------------------------------- */ +void +tty_change_screen_size (void) +{ +#if defined(TIOCGWINSZ) && NCURSES_VERSION_MAJOR >= 4 + struct winsize winsz; + + winsz.ws_col = winsz.ws_row = 0; + +#ifndef NCURSES_VERSION + tty_noraw_mode (); + tty_reset_screen (); +#endif + + /* Ioctl on the STDIN_FILENO */ + ioctl (fileno (stdout), TIOCGWINSZ, &winsz); + if (winsz.ws_col != 0 && winsz.ws_row != 0) + { +#if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM) + resizeterm (winsz.ws_row, winsz.ws_col); + clearok (stdscr, TRUE); /* sigwinch's should use a semaphore! */ +#else + COLS = winsz.ws_col; + LINES = winsz.ws_row; +#endif + } +#endif /* defined(TIOCGWINSZ) || NCURSES_VERSION_MAJOR >= 4 */ + +#ifdef HAVE_SUBSHELL_SUPPORT + if (mc_global.tty.use_subshell) + tty_resize (mc_global.tty.subshell_pty); +#endif +} + +/* --------------------------------------------------------------------------------------------- */ + void tty_reset_prog_mode (void) { diff --git a/lib/tty/tty-slang.c b/lib/tty/tty-slang.c index 0800571fc..543c860c3 100644 --- a/lib/tty/tty-slang.c +++ b/lib/tty/tty-slang.c @@ -34,10 +34,12 @@ #include #include #include -#include #include /* size_t */ #include -#include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#include #include "lib/global.h" #include "lib/strutil.h" /* str_term_form */ @@ -128,22 +130,14 @@ static const struct /* *INDENT-ON* */ }; +/* --------------------------------------------------------------------------------------------- */ /*** file scope functions ************************************************************************/ /* --------------------------------------------------------------------------------------------- */ static void tty_setup_sigwinch (void (*handler) (int)) { -#ifdef SIGWINCH - struct sigaction act, oact; - act.sa_handler = handler; - sigemptyset (&act.sa_mask); - act.sa_flags = 0; -#ifdef SA_RESTART - act.sa_flags |= SA_RESTART; -#endif /* SA_RESTART */ - sigaction (SIGWINCH, &act, &oact); -#endif /* SIGWINCH */ + (void) SLsignal (SIGWINCH, handler); } /* --------------------------------------------------------------------------------------------- */ @@ -153,8 +147,8 @@ sigwinch_handler (int dummy) { (void) dummy; - tty_change_screen_size (); mc_global.tty.winch_flag = 1; + (void) SLsignal (SIGWINCH, sigwinch_handler); } /* --------------------------------------------------------------------------------------------- */ @@ -372,6 +366,20 @@ tty_shutdown (void) } } +/* --------------------------------------------------------------------------------------------- */ + +void +tty_change_screen_size (void) +{ + SLtt_get_screen_size (); + SLsmg_reinit_smg (); + +#ifdef HAVE_SUBSHELL_SUPPORT + if (mc_global.tty.use_subshell) + tty_resize (mc_global.tty.subshell_pty); +#endif +} + /* --------------------------------------------------------------------------------------------- */ /* Done each time we come back from done mode */ diff --git a/lib/tty/tty.c b/lib/tty/tty.c index e4011e614..8a40b9904 100644 --- a/lib/tty/tty.c +++ b/lib/tty/tty.c @@ -247,38 +247,6 @@ tty_resize (int fd) /* --------------------------------------------------------------------------------------------- */ -void -tty_change_screen_size (void) -{ -#if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 -#if defined TIOCGWINSZ - struct winsize winsz; - - winsz.ws_col = winsz.ws_row = 0; - /* Ioctl on the STDIN_FILENO */ - ioctl (0, TIOCGWINSZ, &winsz); - if (winsz.ws_col && winsz.ws_row) - { -#if defined(NCURSES_VERSION) && defined(HAVE_RESIZETERM) - resizeterm (winsz.ws_row, winsz.ws_col); - clearok (stdscr, TRUE); /* sigwinch's should use a semaphore! */ -#else - COLS = winsz.ws_col; - LINES = winsz.ws_row; -#endif -#ifdef HAVE_SUBSHELL_SUPPORT - if (!mc_global.tty.use_subshell) - return; - - tty_resize (mc_global.tty.subshell_pty); -#endif - } -#endif /* TIOCGWINSZ */ -#endif /* defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 */ -} - -/* --------------------------------------------------------------------------------------------- */ - void tty_init_xterm_support (gboolean is_xterm) { diff --git a/lib/widget/dialog-switch.c b/lib/widget/dialog-switch.c index 79a11dce3..becc9ebdf 100644 --- a/lib/widget/dialog-switch.c +++ b/lib/widget/dialog-switch.c @@ -32,17 +32,12 @@ #include -/* If TIOCGWINSZ supported, make it available here, because window resizing code - * depends on it... */ -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#include - #include "lib/global.h" #include "lib/tty/tty.h" /* LINES, COLS */ -#include "lib/tty/win.h" /* do_enter_ca_mode() */ #include "lib/tty/color.h" /* tty_set_normal_attrs() */ +#ifdef HAVE_SLANG +#include "lib/tty/win.h" /* do_enter_ca_mode() */ +#endif #include "lib/widget.h" #include "lib/event.h" @@ -121,7 +116,6 @@ dialog_switch_goto (GList * dlg) /* --------------------------------------------------------------------------------------------- */ -#if defined TIOCGWINSZ static void dlg_resize_cb (void *data, void *user_data) { @@ -133,7 +127,6 @@ dlg_resize_cb (void *data, void *user_data) else d->winch_pending = TRUE; } -#endif /* --------------------------------------------------------------------------------------------- */ /*** public functions ****************************************************************************/ @@ -374,22 +367,10 @@ void dialog_change_screen_size (void) { mc_global.tty.winch_flag = 0; -#if defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 -#if defined TIOCGWINSZ -#ifndef NCURSES_VERSION - tty_noraw_mode (); - tty_reset_screen (); -#endif tty_change_screen_size (); + #ifdef HAVE_SLANG - /* XSI Curses spec states that portable applications shall not invoke - * initscr() more than once. This kludge could be done within the scope - * of the specification by using endwin followed by a refresh (in fact, - * more than one curses implementation does this); it is guaranteed to work - * only with slang. - */ - SLsmg_init_smg (); do_enter_ca_mode (); tty_keypad (TRUE); tty_nodelay (FALSE); @@ -402,9 +383,6 @@ dialog_change_screen_size (void) /* Now, force the redraw */ repaint_screen (); - -#endif /* TIOCGWINSZ */ -#endif /* defined(HAVE_SLANG) || NCURSES_VERSION_MAJOR >= 4 */ } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/execute.c b/src/execute.c index 66af51e55..192cb04d5 100644 --- a/src/execute.c +++ b/src/execute.c @@ -317,6 +317,8 @@ toggle_panels (void) vfs_path_t **new_dir_p; #endif /* HAVE_SUBSHELL_SUPPORT */ + SIG_ATOMIC_VOLATILE_T was_sigwinch = 0; + channels_down (); disable_mouse (); if (clear_before_exec) @@ -386,6 +388,13 @@ toggle_panels (void) if (mc_global.tty.alternate_plus_minus) application_keypad_mode (); + /* HACK: + * Save sigwinch flag that will be reset in mc_refresh() called via update_panels(). + * There is some problem with screen redraw in ncurses-based mc in this situation. + */ + was_sigwinch = mc_global.tty.winch_flag; + mc_global.tty.winch_flag = 0; + #ifdef HAVE_SUBSHELL_SUPPORT if (mc_global.tty.use_subshell) { @@ -406,7 +415,11 @@ toggle_panels (void) update_panels (UP_OPTIMIZE, UP_KEEPSEL); update_xterm_title_path (); } - repaint_screen (); + + if (was_sigwinch != 0 || mc_global.tty.winch_flag != 0) + dialog_change_screen_size (); + else + repaint_screen (); } /* --------------------------------------------------------------------------------------------- */ diff --git a/src/subshell.c b/src/subshell.c index 2a59e7f7a..5b4852d5b 100644 --- a/src/subshell.c +++ b/src/subshell.c @@ -195,12 +195,13 @@ write_all (int fd, const void *buf, size_t count) { if (errno == EINTR) { + if (mc_global.tty.winch_flag) + tty_change_screen_size (); + continue; } - else - { - return written > 0 ? written : ret; - } + + return written > 0 ? written : ret; } count -= ret; written += ret; @@ -502,10 +503,14 @@ feed_subshell (int how, int fail_on_error) if (select (maxfdp + 1, &read_set, NULL, NULL, wptr) == -1) { - /* Despite using SA_RESTART, we still have to check for this */ if (errno == EINTR) + { + if (mc_global.tty.winch_flag) + tty_change_screen_size (); + continue; /* try all over again */ + } tcsetattr (STDOUT_FILENO, TCSANOW, &shell_mode); fprintf (stderr, "select (FD_SETSIZE, &read_set...): %s\r\n", unix_error_string (errno)); @@ -1002,12 +1007,15 @@ read_subshell_prompt (void) if (rc == -1) { if (errno == EINTR) - continue; - else { - fprintf (stderr, "select (FD_SETSIZE, &tmp...): %s\r\n", unix_error_string (errno)); - exit (EXIT_FAILURE); + if (mc_global.tty.winch_flag) + tty_change_screen_size (); + + continue; } + + fprintf (stderr, "select (FD_SETSIZE, &tmp...): %s\r\n", unix_error_string (errno)); + exit (EXIT_FAILURE); } bytes = read (mc_global.tty.subshell_pty, pty_buffer, sizeof (pty_buffer));