0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.1.0304: no redraw when using a STOP signal on Vim and then CONT

Problem:    No redraw when using a STOP signal on Vim and then a CONT signal.
Solution:   Catch the CONT signal and set the terminal to raw mode.  This is
            like 8.1.0244 but without the screen redraw and a fix for
            multi-threading suggested by Dominique Pelle.
This commit is contained in:
Bram Moolenaar
2018-08-21 13:09:10 +02:00
parent c26f7c6053
commit 2e31048c30
4 changed files with 74 additions and 34 deletions

View File

@@ -1228,14 +1228,35 @@ deathtrap SIGDEFARG(sigarg)
SIGRETURN; SIGRETURN;
} }
#if defined(_REENTRANT) && defined(SIGCONT)
/* /*
* On Solaris with multi-threading, suspending might not work immediately. * Invoked after receiving SIGCONT. We don't know what happened while
* Catch the SIGCONT signal, which will be used as an indication whether the * sleeping, deal with part of that.
* suspending has been done or not. */
static void
after_sigcont(void)
{
# ifdef FEAT_TITLE
// Don't change "oldtitle" in a signal handler, set a flag to obtain it
// again later.
oldtitle_outdated = TRUE;
# endif
settmode(TMODE_RAW);
need_check_timestamps = TRUE;
did_check_timestamps = FALSE;
}
#if defined(SIGCONT)
static RETSIGTYPE sigcont_handler SIGPROTOARG;
static volatile int in_mch_suspend = FALSE;
/*
* With multi-threading, suspending might not work immediately. Catch the
* SIGCONT signal, which will be used as an indication whether the suspending
* has been done or not.
* *
* On Linux, signal is not always handled immediately either. * On Linux, signal is not always handled immediately either.
* See https://bugs.launchpad.net/bugs/291373 * See https://bugs.launchpad.net/bugs/291373
* Probably because the signal is handled in another thread.
* *
* volatile because it is used in signal handler sigcont_handler(). * volatile because it is used in signal handler sigcont_handler().
*/ */
@@ -1248,7 +1269,22 @@ static RETSIGTYPE sigcont_handler SIGPROTOARG;
static RETSIGTYPE static RETSIGTYPE
sigcont_handler SIGDEFARG(sigarg) sigcont_handler SIGDEFARG(sigarg)
{ {
sigcont_received = TRUE; if (in_mch_suspend)
{
sigcont_received = TRUE;
}
else
{
// We didn't suspend ourselves, assume we were stopped by a SIGSTOP
// signal (which can't be intercepted) and get a SIGCONT. Need to get
// back to a sane mode. We should redraw, but we can't really do that
// in a signal handler, do a redraw later.
after_sigcont();
redraw_later(CLEAR);
cursor_on_force();
out_flush();
}
SIGRETURN; SIGRETURN;
} }
#endif #endif
@@ -1331,6 +1367,8 @@ mch_suspend(void)
{ {
/* BeOS does have SIGTSTP, but it doesn't work. */ /* BeOS does have SIGTSTP, but it doesn't work. */
#if defined(SIGTSTP) && !defined(__BEOS__) #if defined(SIGTSTP) && !defined(__BEOS__)
in_mch_suspend = TRUE;
out_flush(); /* needed to make cursor visible on some systems */ out_flush(); /* needed to make cursor visible on some systems */
settmode(TMODE_COOK); settmode(TMODE_COOK);
out_flush(); /* needed to disable mouse on some systems */ out_flush(); /* needed to disable mouse on some systems */
@@ -1338,40 +1376,32 @@ mch_suspend(void)
# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11) # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
loose_clipboard(); loose_clipboard();
# endif # endif
# if defined(SIGCONT)
# if defined(_REENTRANT) && defined(SIGCONT)
sigcont_received = FALSE; sigcont_received = FALSE;
# endif # endif
kill(0, SIGTSTP); /* send ourselves a STOP signal */ kill(0, SIGTSTP); /* send ourselves a STOP signal */
# if defined(_REENTRANT) && defined(SIGCONT)
# if defined(SIGCONT)
/* /*
* Wait for the SIGCONT signal to be handled. It generally happens * Wait for the SIGCONT signal to be handled. It generally happens
* immediately, but somehow not all the time. Do not call pause() * immediately, but somehow not all the time, probably because it's handled
* because there would be race condition which would hang Vim if * in another thread. Do not call pause() because there would be race
* signal happened in between the test of sigcont_received and the * condition which would hang Vim if signal happened in between the test of
* call to pause(). If signal is not yet received, call sleep(0) * sigcont_received and the call to pause(). If signal is not yet received,
* to just yield CPU. Signal should then be received. If somehow * sleep 0, 1, 2, 3 ms. Don't bother waiting further if signal is not
* it's still not received, sleep 1, 2, 3 ms. Don't bother waiting * received after 1+2+3 ms (not expected to happen).
* further if signal is not received after 1+2+3+4 ms (not expected
* to happen).
*/ */
{ {
long wait_time; long wait_time;
for (wait_time = 0; !sigcont_received && wait_time <= 3L; wait_time++) for (wait_time = 0; !sigcont_received && wait_time <= 3L; wait_time++)
/* Loop is not entered most of the time */
mch_delay(wait_time, FALSE); mch_delay(wait_time, FALSE);
} }
# endif # endif
in_mch_suspend = FALSE;
# ifdef FEAT_TITLE after_sigcont();
/*
* Set oldtitle to NULL, so the current title is obtained again.
*/
VIM_CLEAR(oldtitle);
# endif
settmode(TMODE_RAW);
need_check_timestamps = TRUE;
did_check_timestamps = FALSE;
#else #else
suspend_shell(); suspend_shell();
#endif #endif
@@ -1411,7 +1441,7 @@ set_signals(void)
#ifdef SIGTSTP #ifdef SIGTSTP
signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL); signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
#endif #endif
#if defined(_REENTRANT) && defined(SIGCONT) #if defined(SIGCONT)
signal(SIGCONT, sigcont_handler); signal(SIGCONT, sigcont_handler);
#endif #endif
@@ -1470,7 +1500,7 @@ catch_int_signal(void)
reset_signals(void) reset_signals(void)
{ {
catch_signals(SIG_DFL, SIG_DFL); catch_signals(SIG_DFL, SIG_DFL);
#if defined(_REENTRANT) && defined(SIGCONT) #if defined(SIGCONT)
/* SIGCONT isn't in the list, because its default action is ignore */ /* SIGCONT isn't in the list, because its default action is ignore */
signal(SIGCONT, SIG_DFL); signal(SIGCONT, SIG_DFL);
#endif #endif
@@ -1533,7 +1563,7 @@ block_signals(sigset_t *set)
for (i = 0; signal_info[i].sig != -1; i++) for (i = 0; signal_info[i].sig != -1; i++)
sigaddset(&newset, signal_info[i].sig); sigaddset(&newset, signal_info[i].sig);
# if defined(_REENTRANT) && defined(SIGCONT) # if defined(SIGCONT)
/* SIGCONT isn't in the list, because its default action is ignore */ /* SIGCONT isn't in the list, because its default action is ignore */
sigaddset(&newset, SIGCONT); sigaddset(&newset, SIGCONT);
# endif # endif

View File

@@ -52,6 +52,7 @@ void setmouse(void);
int mouse_has(int c); int mouse_has(int c);
int mouse_model_popup(void); int mouse_model_popup(void);
void scroll_start(void); void scroll_start(void);
void cursor_on_force(void);
void cursor_on(void); void cursor_on(void);
void cursor_off(void); void cursor_off(void);
void term_cursor_mode(int forced); void term_cursor_mode(int forced);

View File

@@ -3834,16 +3834,23 @@ scroll_start(void)
static int cursor_is_off = FALSE; static int cursor_is_off = FALSE;
/* /*
* Enable the cursor. * Enable the cursor without checking if it's already enabled.
*/
void
cursor_on_force(void)
{
out_str(T_VE);
cursor_is_off = FALSE;
}
/*
* Enable the cursor if it's currently off.
*/ */
void void
cursor_on(void) cursor_on(void)
{ {
if (cursor_is_off) if (cursor_is_off)
{ cursor_on_force();
out_str(T_VE);
cursor_is_off = FALSE;
}
} }
/* /*

View File

@@ -794,6 +794,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
304,
/**/ /**/
303, 303,
/**/ /**/