]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.1.0304: no redraw when using a STOP signal on Vim and then CONT v8.1.0304
authorBram Moolenaar <Bram@vim.org>
Tue, 21 Aug 2018 11:09:10 +0000 (13:09 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 21 Aug 2018 11:09:10 +0000 (13:09 +0200)
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.

src/os_unix.c
src/proto/term.pro
src/term.c
src/version.c

index 39ace2e295177ab01cb98965ea1cfd906a8e7ef5..80c61755b1819f28f28392c11a0d9dcd443f78cd 100644 (file)
@@ -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
index c68d7ab033e819e49526864fae5e8053bfa729bb..1b8ab5f0dd833f9a6852761224491cbacd1c0841 100644 (file)
@@ -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);
index 97ddf8bc4a1295cf875411b7c3ad30e77c8cb10c..cede4b89491ccba4aa47e544b56e53c80cdc0de5 100644 (file)
@@ -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();
 }
 
 /*
index d382ff316d3c93bd5c93a4ac5b78f1e00cb064ff..8fa17ec79042071edaee73930d605ab3c59bbdcc 100644 (file)
@@ -794,6 +794,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    304,
 /**/
     303,
 /**/