aboutsummaryrefslogtreecommitdiff
path: root/src/unix/tty.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/unix/tty.c')
-rw-r--r--src/unix/tty.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/src/unix/tty.c b/src/unix/tty.c
index d099bdb3..793054ba 100644
--- a/src/unix/tty.c
+++ b/src/unix/tty.c
@@ -335,6 +335,37 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
}
+void uv__tty_close(uv_tty_t* handle) {
+ int expected;
+ int fd;
+
+ fd = handle->io_watcher.fd;
+ if (fd == -1)
+ goto done;
+
+ /* This is used for uv_tty_reset_mode() */
+ do
+ expected = 0;
+ while (!atomic_compare_exchange_strong(&termios_spinlock, &expected, 1));
+
+ if (fd == orig_termios_fd) {
+ /* XXX(bnoordhuis) the tcsetattr is probably wrong when there are still
+ * other uv_tty_t handles active that refer to the same tty/pty but it's
+ * hard to recognize that particular situation without maintaining some
+ * kind of process-global data structure, and that still won't work in a
+ * multi-process setup.
+ */
+ uv__tcsetattr(fd, TCSANOW, &orig_termios);
+ orig_termios_fd = -1;
+ }
+
+ atomic_store(&termios_spinlock, 0);
+
+done:
+ uv__stream_close((uv_stream_t*) handle);
+}
+
+
int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) {
struct winsize ws;
int err;
@@ -452,7 +483,7 @@ int uv_tty_reset_mode(void) {
saved_errno = errno;
if (atomic_exchange(&termios_spinlock, 1))
- return UV_EBUSY; /* In uv_tty_set_mode(). */
+ return UV_EBUSY; /* In uv_tty_set_mode() or uv__tty_close(). */
err = 0;
if (orig_termios_fd != -1)