Merge branch '117_sigwinch'

* 117_sigwinch:
  Ticket #117: refactoring of SIGWINCH hangling.
This commit is contained in:
Andrew Borodin 2019-09-01 19:25:27 +03:00
commit af65483e97
14 changed files with 161 additions and 20 deletions

View File

@ -104,8 +104,7 @@ mc_global_t mc_global = {
.disable_colors = FALSE,
.ugly_line_drawing = FALSE,
.old_mouse = FALSE,
.alternate_plus_minus = FALSE,
.winch_flag = 0
.alternate_plus_minus = FALSE
},
.vfs =

View File

@ -275,9 +275,6 @@ typedef struct
/* If true, use + and \ keys normally and select/unselect do if M-+ / M-\.
and M-- and keypad + / - */
gboolean alternate_plus_minus;
/* Set if the window has changed it's size */
SIG_ATOMIC_VOLATILE_T winch_flag;
} tty;
struct

View File

@ -16,7 +16,8 @@ TTY_SRC = \
color.c color.h \
key.c key.h keyxdef.c \
mouse.c mouse.h \
tty.c tty.h tty-internal.h \
tty-internal.c tty-internal.h \
tty.c tty.h \
win.c win.h
if HAVE_TEXTMODE_X11_SUPPORT

View File

@ -2028,7 +2028,7 @@ tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
}
}
if (!block || mc_global.tty.winch_flag != 0)
if (!block || tty_got_winch ())
{
time_addr = &time_out;
time_out.tv_sec = 0;
@ -2048,7 +2048,7 @@ tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
{
if (redo_event)
return EV_MOUSE;
if (!block || mc_global.tty.winch_flag != 0)
if (!block || tty_got_winch ())
return EV_NONE;
vfs_timeout_handler ();
}

104
lib/tty/tty-internal.c Normal file
View File

@ -0,0 +1,104 @@
/*
Internal stuff of the terminal controlling library.
Copyright (C) 2019
Free Software Foundation, Inc.
Written by:
Andrew Borodin <aborodin@vmail.ru>, 2019.
This file is part of the Midnight Commander.
The Midnight Commander is free software: you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
The Midnight Commander is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/** \file
* \brief Source: internal stuff of the terminal controlling library.
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "lib/global.h"
#include "tty-internal.h"
/*** global variables ****************************************************************************/
/* pipe to handle SIGWINCH */
int sigwinch_pipe[2];
/*** file scope macro definitions ****************************************************************/
/*** global variables ****************************************************************************/
/*** file scope type declarations ****************************************************************/
/*** file scope variables ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
/*** file scope functions ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------------------- */
/*** public functions ****************************************************************************/
/* --------------------------------------------------------------------------------------------- */
void
tty_create_winch_pipe (void)
{
int fd_flags;
if (pipe (sigwinch_pipe) == -1)
{
perror (_("Cannot create pipe for SIGWINCH"));
exit (EXIT_FAILURE);
}
/* If we read from an empty pipe, then read(2) will block until data is available.
* If we write to a full pipe, then write(2) blocks until sufficient data has been read
* from the pipe to allow the write to complete..
* Therefore, use nonblocking I/O.
*/
fd_flags = fcntl (sigwinch_pipe[0], F_GETFL, NULL);
if (fd_flags != -1)
{
fd_flags |= O_NONBLOCK | O_CLOEXEC;
fd_flags = fcntl (sigwinch_pipe[0], F_SETFL, fd_flags);
}
if (fd_flags == -1)
{
perror (_("Cannot configure write end of SIGWINCH pipe"));
exit (EXIT_FAILURE);
}
fd_flags = fcntl (sigwinch_pipe[1], F_GETFL, NULL);
if (fd_flags != -1)
{
fd_flags |= O_NONBLOCK | O_CLOEXEC;
fd_flags = fcntl (sigwinch_pipe[1], F_SETFL, fd_flags);
}
if (fd_flags == -1)
{
perror (_("Cannot configure read end of SIGWINCH pipe"));
exit (EXIT_FAILURE);
}
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -30,11 +30,17 @@ extern gboolean mouse_enabled;
extern char *smcup;
extern char *rmcup;
/* pipe to handle SIGWINCH */
extern int sigwinch_pipe[2];
/*** declarations of public functions ************************************************************/
void tty_create_winch_pipe (void);
char *mc_tty_normalize_from_utf8 (const char *);
void tty_init_xterm_support (gboolean is_xterm);
int tty_lowlevel_getch (void);
/*** inline functions ****************************************************************************/
#endif /* MC_TTY_INTERNAL_H */

View File

@ -102,6 +102,8 @@ tty_setup_sigwinch (void (*handler) (int))
#endif /* SA_RESTART */
sigaction (SIGWINCH, &act, &oact);
#endif /* SIGWINCH */
tty_create_winch_pipe ();
}
/* --------------------------------------------------------------------------------------------- */
@ -109,9 +111,12 @@ tty_setup_sigwinch (void (*handler) (int))
static void
sigwinch_handler (int dummy)
{
ssize_t n = 0;
(void) dummy;
mc_global.tty.winch_flag = 1;
n = write (sigwinch_pipe[1], "", 1);
(void) n;
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -139,6 +139,7 @@ static void
tty_setup_sigwinch (void (*handler) (int))
{
(void) SLsignal (SIGWINCH, handler);
tty_create_winch_pipe ();
}
/* --------------------------------------------------------------------------------------------- */
@ -146,9 +147,13 @@ tty_setup_sigwinch (void (*handler) (int))
static void
sigwinch_handler (int dummy)
{
ssize_t n = 0;
(void) dummy;
mc_global.tty.winch_flag = 1;
n = write (sigwinch_pipe[1], "", 1);
(void) n;
(void) SLsignal (SIGWINCH, sigwinch_handler);
}

View File

@ -30,6 +30,7 @@
#include <config.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
@ -164,6 +165,29 @@ tty_got_interrupt (void)
/* --------------------------------------------------------------------------------------------- */
gboolean
tty_got_winch (void)
{
gboolean ret = FALSE;
ssize_t n;
/* merge all SIGWINCH events raised to this moment */
do
{
char x[16];
/* read multiple events at a time */
n = read (sigwinch_pipe[0], &x, sizeof (x));
if (n > 0)
ret = TRUE;
}
while (n > 0 || (n == -1 && errno == EINTR));
return ret;
}
/* --------------------------------------------------------------------------------------------- */
void
tty_print_one_hline (gboolean single)
{

View File

@ -80,6 +80,8 @@ extern void tty_enable_interrupt_key (void);
extern void tty_disable_interrupt_key (void);
extern gboolean tty_got_interrupt (void);
extern gboolean tty_got_winch (void);
extern void tty_reset_prog_mode (void);
extern void tty_reset_shell_mode (void);

View File

@ -338,7 +338,8 @@ mc_refresh (void)
if (mc_global.we_are_background)
return;
#endif /* ENABLE_BACKGROUND */
if (mc_global.tty.winch_flag == 0)
if (!tty_got_winch ())
tty_refresh ();
else
{
@ -355,8 +356,6 @@ dialog_change_screen_size (void)
{
GList *d;
mc_global.tty.winch_flag = 0;
tty_change_screen_size ();
#ifdef HAVE_SLANG

View File

@ -519,7 +519,7 @@ frontend_dlg_run (WDialog * h)
{
int d_key;
if (mc_global.tty.winch_flag != 0)
if (tty_got_winch ())
dialog_change_screen_size ();
if (is_idle ())

View File

@ -531,8 +531,7 @@ toggle_panels (void)
* 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;
was_sigwinch = tty_got_winch ();
#ifdef ENABLE_SUBSHELL
if (mc_global.tty.use_subshell)
@ -555,7 +554,7 @@ toggle_panels (void)
update_xterm_title_path ();
}
if (was_sigwinch != 0 || mc_global.tty.winch_flag != 0)
if (was_sigwinch != 0 || tty_got_winch ())
dialog_change_screen_size ();
else
repaint_screen ();

View File

@ -207,7 +207,7 @@ write_all (int fd, const void *buf, size_t count)
{
if (errno == EINTR)
{
if (mc_global.tty.winch_flag != 0)
if (tty_got_winch ())
tty_change_screen_size ();
continue;
@ -545,7 +545,7 @@ feed_subshell (int how, gboolean fail_on_error)
/* Despite using SA_RESTART, we still have to check for this */
if (errno == EINTR)
{
if (mc_global.tty.winch_flag != 0)
if (tty_got_winch ())
tty_change_screen_size ();
continue; /* try all over again */
@ -1211,7 +1211,7 @@ read_subshell_prompt (void)
{
if (errno == EINTR)
{
if (mc_global.tty.winch_flag != 0)
if (tty_got_winch ())
tty_change_screen_size ();
continue;