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:
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
17
src/term.c
17
src/term.c
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user