summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-08-21 13:09:10 +0200
committerBram Moolenaar <Bram@vim.org>2018-08-21 13:09:10 +0200
commit2e31048c304fb94d6255667783edfe9f4d5894c2 (patch)
treee24528bfd59d4319dfbd86eb0754d2818743b27b
parentc26f7c60532a37a2bf0a5e69aa81081b440dfc38 (diff)
downloadvim-git-8.1.0304.tar.gz
patch 8.1.0304: no redraw when using a STOP signal on Vim and then CONTv8.1.0304
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.
-rw-r--r--src/os_unix.c88
-rw-r--r--src/proto/term.pro1
-rw-r--r--src/term.c17
-rw-r--r--src/version.c2
4 files changed, 74 insertions, 34 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index 39ace2e29..80c61755b 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1228,14 +1228,35 @@ deathtrap SIGDEFARG(sigarg)
SIGRETURN;
}
-#if defined(_REENTRANT) && defined(SIGCONT)
/*
- * On Solaris 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.
+ * Invoked after receiving SIGCONT. We don't know what happened while
+ * sleeping, deal with part of that.
+ */
+ 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.
* 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().
*/
@@ -1248,7 +1269,22 @@ static RETSIGTYPE sigcont_handler SIGPROTOARG;
static RETSIGTYPE
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;
}
#endif
@@ -1331,6 +1367,8 @@ mch_suspend(void)
{
/* BeOS does have SIGTSTP, but it doesn't work. */
#if defined(SIGTSTP) && !defined(__BEOS__)
+ in_mch_suspend = TRUE;
+
out_flush(); /* needed to make cursor visible on some systems */
settmode(TMODE_COOK);
out_flush(); /* needed to disable mouse on some systems */
@@ -1338,40 +1376,32 @@ mch_suspend(void)
# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
loose_clipboard();
# endif
-
-# if defined(_REENTRANT) && defined(SIGCONT)
+# if defined(SIGCONT)
sigcont_received = FALSE;
# endif
+
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
- * immediately, but somehow not all the time. Do not call pause()
- * because there would be race condition which would hang Vim if
- * signal happened in between the test of sigcont_received and the
- * call to pause(). If signal is not yet received, call sleep(0)
- * to just yield CPU. Signal should then be received. If somehow
- * it's still not received, sleep 1, 2, 3 ms. Don't bother waiting
- * further if signal is not received after 1+2+3+4 ms (not expected
- * to happen).
+ * immediately, but somehow not all the time, probably because it's handled
+ * in another thread. Do not call pause() because there would be race
+ * condition which would hang Vim if signal happened in between the test of
+ * sigcont_received and the call to pause(). If signal is not yet received,
+ * sleep 0, 1, 2, 3 ms. Don't bother waiting further if signal is not
+ * received after 1+2+3 ms (not expected to happen).
*/
{
long 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);
}
# endif
+ in_mch_suspend = FALSE;
-# ifdef FEAT_TITLE
- /*
- * 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;
+ after_sigcont();
#else
suspend_shell();
#endif
@@ -1411,7 +1441,7 @@ set_signals(void)
#ifdef SIGTSTP
signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
#endif
-#if defined(_REENTRANT) && defined(SIGCONT)
+#if defined(SIGCONT)
signal(SIGCONT, sigcont_handler);
#endif
@@ -1470,7 +1500,7 @@ catch_int_signal(void)
reset_signals(void)
{
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 */
signal(SIGCONT, SIG_DFL);
#endif
@@ -1533,7 +1563,7 @@ block_signals(sigset_t *set)
for (i = 0; signal_info[i].sig != -1; i++)
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 */
sigaddset(&newset, SIGCONT);
# endif
diff --git a/src/proto/term.pro b/src/proto/term.pro
index c68d7ab03..1b8ab5f0d 100644
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -52,6 +52,7 @@ void setmouse(void);
int mouse_has(int c);
int mouse_model_popup(void);
void scroll_start(void);
+void cursor_on_force(void);
void cursor_on(void);
void cursor_off(void);
void term_cursor_mode(int forced);
diff --git a/src/term.c b/src/term.c
index 97ddf8bc4..cede4b894 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3834,16 +3834,23 @@ scroll_start(void)
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
cursor_on(void)
{
if (cursor_is_off)
- {
- out_str(T_VE);
- cursor_is_off = FALSE;
- }
+ cursor_on_force();
}
/*
diff --git a/src/version.c b/src/version.c
index d382ff316..8fa17ec79 100644
--- a/src/version.c
+++ b/src/version.c
@@ -795,6 +795,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 304,
+/**/
303,
/**/
302,