aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin
diff options
context:
space:
mode:
authorTakashi Yano <takashi.yano@nifty.ne.jp>2025-04-09 14:57:54 +0900
committerTakashi Yano <takashi.yano@nifty.ne.jp>2025-04-09 15:11:00 +0900
commitd35cc82b5ec15bb8a5fe0fe11e183d1887992e99 (patch)
treed1a90d7003a5eef4b837e45f8e36035dbd55bf2d /winsup/cygwin
parentd29943e56dc5e30e219b7da114b0b0c31acd8cbc (diff)
downloadnewlib-main.zip
newlib-main.tar.gz
newlib-main.tar.bz2
Cygwin: termios: Implement tcflow(), tcdrain(), TCXONC, TIOCINQHEADgithub/mastergithub/mainmastermain
Previously, tcflow() and tcdrain() were missing from console and pty. ioctl() command: TCXONC, TIOCINQ, and TCFLSH were also missing. Due to this, "stress-ng --pty 1" failed. This patch implements them. Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/fhandler/console.cc30
-rw-r--r--winsup/cygwin/fhandler/pty.cc30
-rw-r--r--winsup/cygwin/fhandler/termios.cc31
-rw-r--r--winsup/cygwin/include/sys/termios.h1
-rw-r--r--winsup/cygwin/local_includes/fhandler.h7
-rw-r--r--winsup/cygwin/local_includes/tty.h6
6 files changed, 95 insertions, 10 deletions
diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index a38487f..c613643 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -509,7 +509,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
case not_signalled_but_done:
case done_with_debugger:
processed = true;
- ttyp->output_stopped = false;
+ ttyp->output_stopped &= ~BY_VSTOP;
if (ti.c_lflag & NOFLSH)
goto remove_record;
con.num_processed = 0;
@@ -1144,6 +1144,15 @@ fhandler_console::read (void *pv, size_t& buflen)
push_process_state process_state (PID_TTYIN);
+ if (get_ttyp ()->input_stopped && is_nonblocking ())
+ {
+ set_errno (EAGAIN);
+ buflen = (size_t) -1;
+ return;
+ }
+ while (get_ttyp ()->input_stopped)
+ cygwait (10);
+
size_t copied_chars = 0;
DWORD timeout = is_nonblocking () ? 0 :
@@ -2131,6 +2140,7 @@ fhandler_console::ioctl (unsigned int cmd, void *arg)
release_output_mutex ();
return -1;
case FIONREAD:
+ case TIOCINQ:
{
DWORD n;
int ret = 0;
@@ -2183,6 +2193,14 @@ fhandler_console::ioctl (unsigned int cmd, void *arg)
return 0;
}
break;
+ case TCXONC:
+ res = this->tcflow ((int)(intptr_t) arg);
+ release_output_mutex ();
+ return res;
+ case TCFLSH:
+ res = this->tcflush ((int)(intptr_t) arg);
+ release_output_mutex ();
+ return res;
}
release_output_mutex ();
@@ -4172,8 +4190,8 @@ fhandler_console::write (const void *vsrc, size_t len)
void
fhandler_console::doecho (const void *str, DWORD len)
{
- bool stopped = get_ttyp ()->output_stopped;
- get_ttyp ()->output_stopped = false;
+ int stopped = get_ttyp ()->output_stopped;
+ get_ttyp ()->output_stopped = 0;
write (str, len);
get_ttyp ()->output_stopped = stopped;
}
@@ -4711,3 +4729,9 @@ fhandler_console::cons_mode_on_close ()
return tty::restore; /* otherwise, restore */
}
+
+int
+fhandler_console::tcdrain ()
+{
+ return 0;
+}
diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
index 3128b92..b882b90 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -1304,6 +1304,15 @@ fhandler_pty_slave::read (void *ptr, size_t& len)
push_process_state process_state (PID_TTYIN);
+ if (get_ttyp ()->input_stopped && is_nonblocking ())
+ {
+ set_errno (EAGAIN);
+ len = (size_t) -1;
+ return;
+ }
+ while (get_ttyp ()->input_stopped)
+ cygwait (10);
+
if (ptr) /* Indicating not tcflush(). */
mask_switch_to_nat_pipe (true, true);
@@ -1650,6 +1659,7 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
retval = this->tcsetpgrp ((pid_t) (intptr_t) arg);
goto out;
case FIONREAD:
+ case TIOCINQ:
{
DWORD n;
if (!bytes_available (n))
@@ -1664,6 +1674,12 @@ fhandler_pty_slave::ioctl (unsigned int cmd, void *arg)
}
}
goto out;
+ case TCXONC:
+ retval = this->tcflow ((int)(intptr_t) arg);
+ goto out;
+ case TCFLSH:
+ retval = this->tcflush ((int)(intptr_t) arg);
+ goto out;
default:
return fhandler_base::ioctl (cmd, arg);
}
@@ -2342,6 +2358,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
case TIOCSPGRP:
return this->tcsetpgrp ((pid_t) (intptr_t) arg);
case FIONREAD:
+ case TIOCINQ:
{
DWORD n;
if (!bytes_available (n))
@@ -2352,6 +2369,10 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg)
*(int *) arg = (int) n;
}
break;
+ case TCXONC:
+ return this->tcflow ((int)(intptr_t) arg);
+ case TCFLSH:
+ return this->tcflush ((int)(intptr_t) arg);
default:
return fhandler_base::ioctl (cmd, arg);
}
@@ -4194,3 +4215,12 @@ fhandler_pty_common::resume_from_temporarily_attach (DWORD resume_pid)
}
release_attach_mutex ();
}
+
+int
+fhandler_pty_common::tcdrain ()
+{
+ DWORD n;
+ while (bytes_available (n) && n > 0)
+ cygwait (10);
+ return 0;
+}
diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/termios.cc
index a3cecdb..19d6220 100644
--- a/winsup/cygwin/fhandler/termios.cc
+++ b/winsup/cygwin/fhandler/termios.cc
@@ -491,16 +491,16 @@ fhandler_termios::process_stop_start (char c, tty *ttyp)
{
if (CCEQ (ti.c_cc[VSTOP], c))
{
- ttyp->output_stopped = true;
+ ttyp->output_stopped |= BY_VSTOP;
return true;
}
else if (CCEQ (ti.c_cc[VSTART], c))
{
restart_output:
- ttyp->output_stopped = false;
+ ttyp->output_stopped &= ~BY_VSTOP;
return true;
}
- else if ((ti.c_iflag & IXANY) && ttyp->output_stopped)
+ else if ((ti.c_iflag & IXANY) && (ttyp->output_stopped & BY_VSTOP))
goto restart_output;
}
if ((ti.c_lflag & ICANON) && (ti.c_lflag & IEXTEN)
@@ -540,7 +540,7 @@ fhandler_termios::line_edit (const char *rptr, size_t nread, termios& ti,
fallthrough;
case not_signalled_but_done:
case done_with_debugger:
- get_ttyp ()->output_stopped = false;
+ get_ttyp ()->output_stopped &= ~BY_VSTOP;
continue;
case not_signalled_with_nat_reader:
disable_eof_key = true;
@@ -915,3 +915,26 @@ fhandler_termios::get_console_process_id (DWORD pid, bool match,
}
return res_pri ?: res;
}
+
+int
+fhandler_termios::tcflow (int action)
+{
+ switch (action)
+ {
+ case TCOOFF:
+ get_ttyp ()->output_stopped |= BY_TCFLOW;
+ return 0;
+ case TCOON:
+ get_ttyp ()->output_stopped = 0;
+ return 0;
+ case TCIOFF:
+ get_ttyp ()->input_stopped |= BY_TCFLOW;
+ return 0;
+ case TCION:
+ get_ttyp ()->input_stopped = 0;
+ return 0;
+ default:
+ set_errno (EINVAL);
+ return -1;
+ }
+}
diff --git a/winsup/cygwin/include/sys/termios.h b/winsup/cygwin/include/sys/termios.h
index d1b4a0a..4c03042 100644
--- a/winsup/cygwin/include/sys/termios.h
+++ b/winsup/cygwin/include/sys/termios.h
@@ -18,6 +18,7 @@ details. */
#define TIOCMBIC 0x5417
#define TIOCMSET 0x5418
#define TIOCINQ 0x541B
+#define TCXONC 0x540A
#define TIOCSCTTY 0x540E
/* TIOCINQ is utilized instead of FIONREAD which has been
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
index 8c71d84..2177cec 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -1979,6 +1979,7 @@ class fhandler_termios: public fhandler_base
virtual off_t lseek (off_t, int);
pid_t tcgetsid ();
virtual int fstat (struct stat *buf);
+ int tcflow (int);
fhandler_termios (void *) {}
@@ -2143,12 +2144,12 @@ class dev_console
char cons_rabuf[40]; // cannot get longer than char buf[40] in char_command
char *cons_rapoi;
bool cursor_key_app_mode;
- bool disable_master_thread;
+ volatile bool disable_master_thread;
tty::cons_mode curr_input_mode;
tty::cons_mode curr_output_mode;
DWORD prev_input_mode;
DWORD prev_output_mode;
- bool master_thread_suspended;
+ volatile bool master_thread_suspended;
int num_processed; /* Number of input events in the current input buffer
already processed by cons_master_thread(). */
@@ -2273,6 +2274,7 @@ private:
int tcflush (int);
int tcsetattr (int a, const struct termios *t);
int tcgetattr (struct termios *t);
+ int tcdrain ();
int ioctl (unsigned int cmd, void *);
int init (HANDLE, DWORD, mode_t, int64_t = 0);
@@ -2391,6 +2393,7 @@ class fhandler_pty_common: public fhandler_termios
DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms);
void __release_output_mutex (const char *fn, int ln);
+ int tcdrain ();
int close (int flag = -1);
off_t lseek (off_t, int);
bool bytes_available (DWORD& n);
diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_includes/tty.h
index 2a047d7..a418ab1 100644
--- a/winsup/cygwin/local_includes/tty.h
+++ b/winsup/cygwin/local_includes/tty.h
@@ -30,6 +30,9 @@ details. */
#define MIN_CTRL_C_SLOP 50
#endif
+#define BY_TCFLOW 2
+#define BY_VSTOP 1
+
typedef void *HPCON;
#include "devices.h"
@@ -43,7 +46,8 @@ class tty_min
public:
pid_t pgid;
- bool output_stopped; /* FIXME: Maybe do this with a mutex someday? */
+ volatile int output_stopped; /* FIXME: Maybe do this with a mutex someday? */
+ volatile int input_stopped;
fh_devices ntty;
ULONGLONG last_ctrl_c; /* tick count of last ctrl-c */
bool is_console;