- After commit 6cc299f0e20e4b76f7dbab5ea8c296ffa4859b62, outputs of
  cygwin programs which call both printf() and WriteConsole() are
  frequently distorted. This patch fixes the issue.
---
 winsup/cygwin/fhandler.h      |  2 ++
 winsup/cygwin/fhandler_tty.cc | 46 ++++++++++++++++++++++++-----------
 2 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 35190c0fe..2c18b215a 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2209,6 +2209,8 @@ class fhandler_pty_slave: public fhandler_pty_common
   }
   void setup_locale (void);
   void set_freeconsole_on_close (bool val);
+  void trigger_redraw_screen (void);
+  void wait_pcon_fwd (void);
 };
 
 #define __ptsname(buf, unit) __small_sprintf ((buf), "/dev/pty%d", (unit))
diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc
index 71a1f42ba..ea971e11f 100644
--- a/winsup/cygwin/fhandler_tty.cc
+++ b/winsup/cygwin/fhandler_tty.cc
@@ -1109,7 +1109,7 @@ skip_console_setting:
     }
   else if ((fd == 1 || fd == 2) && !get_ttyp ()->switch_to_pcon_out)
     {
-      cygwait (get_ttyp ()->fwd_done, INFINITE);
+      wait_pcon_fwd ();
       if (get_ttyp ()->pcon_pid == 0 ||
          kill (get_ttyp ()->pcon_pid, 0) != 0)
        get_ttyp ()->pcon_pid = myself->pid;
@@ -1152,7 +1152,7 @@ fhandler_pty_slave::reset_switch_to_pcon (void)
     }
   if (get_ttyp ()->switch_to_pcon_out)
     /* Wait for pty_master_fwd_thread() */
-    cygwait (get_ttyp ()->fwd_done, INFINITE);
+    wait_pcon_fwd ();
   get_ttyp ()->pcon_pid = 0;
   get_ttyp ()->switch_to_pcon_in = false;
   get_ttyp ()->switch_to_pcon_out = false;
@@ -2680,6 +2680,34 @@ fhandler_pty_slave::set_freeconsole_on_close (bool val)
   freeconsole_on_close = val;
 }
 
+void
+fhandler_pty_slave::trigger_redraw_screen (void)
+{
+  /* Forcibly redraw screen based on console screen buffer. */
+  /* The following code triggers redrawing the screen. */
+  CONSOLE_SCREEN_BUFFER_INFO sbi;
+  GetConsoleScreenBufferInfo (get_output_handle (), &sbi);
+  SMALL_RECT rect = {0, 0,
+    (SHORT) (sbi.dwSize.X -1), (SHORT) (sbi.dwSize.Y - 1)};
+  COORD dest = {0, 0};
+  CHAR_INFO fill = {' ', 0};
+  ScrollConsoleScreenBuffer (get_output_handle (), &rect, NULL, dest, &fill);
+}
+
+void
+fhandler_pty_slave::wait_pcon_fwd (void)
+{
+  /* The transfer may be interruted once, so wait twice. */
+  /* First time */
+  ResetEvent (get_ttyp ()->fwd_done);
+  trigger_redraw_screen ();
+  cygwait (get_ttyp ()->fwd_done, INFINITE);
+  /* Second time */
+  ResetEvent (get_ttyp ()->fwd_done);
+  trigger_redraw_screen ();
+  cygwait (get_ttyp ()->fwd_done, INFINITE);
+}
+
 void
 fhandler_pty_slave::fixup_after_attach (bool native_maybe, int fd_set)
 {
@@ -2727,7 +2755,7 @@ fhandler_pty_slave::fixup_after_attach (bool 
native_maybe, int fd_set)
              DWORD mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
              SetConsoleMode (get_output_handle (), mode);
              if (!get_ttyp ()->switch_to_pcon_out)
-               cygwait (get_ttyp ()->fwd_done, INFINITE);
+               wait_pcon_fwd ();
              if (get_ttyp ()->pcon_pid == 0 ||
                  kill (get_ttyp ()->pcon_pid, 0) != 0)
                get_ttyp ()->pcon_pid = myself->pid;
@@ -2735,16 +2763,7 @@ fhandler_pty_slave::fixup_after_attach (bool 
native_maybe, int fd_set)
 
              if (get_ttyp ()->need_redraw_screen)
                {
-                 /* Forcibly redraw screen based on console screen buffer. */
-                 /* The following code triggers redrawing the screen. */
-                 CONSOLE_SCREEN_BUFFER_INFO sbi;
-                 GetConsoleScreenBufferInfo (get_output_handle (), &sbi);
-                 SMALL_RECT rect = {0, 0,
-                   (SHORT) (sbi.dwSize.X -1), (SHORT) (sbi.dwSize.Y - 1)};
-                 COORD dest = {0, 0};
-                 CHAR_INFO fill = {' ', 0};
-                 ScrollConsoleScreenBuffer (get_output_handle (),
-                                            &rect, NULL, dest, &fill);
+                 trigger_redraw_screen ();
                  get_ttyp ()->need_redraw_screen = false;
                }
            }
@@ -3016,7 +3035,6 @@ fhandler_pty_master::pty_master_fwd_thread ()
          termios_printf ("ReadFile for forwarding failed, %E");
          break;
        }
-      ResetEvent (get_ttyp ()->fwd_done);
       ssize_t wlen = rlen;
       char *ptr = outbuf;
       if (get_pseudo_console ())
-- 
2.21.0

Reply via email to