aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/unix/core.c2
-rw-r--r--src/unix/internal.h3
-rw-r--r--src/unix/tty.c33
3 files changed, 36 insertions, 2 deletions
diff --git a/src/unix/core.c b/src/unix/core.c
index cfa65023..b74552ef 100644
--- a/src/unix/core.c
+++ b/src/unix/core.c
@@ -156,7 +156,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
break;
case UV_TTY:
- uv__stream_close((uv_stream_t*)handle);
+ uv__tty_close((uv_tty_t*)handle);
break;
case UV_TCP:
diff --git a/src/unix/internal.h b/src/unix/internal.h
index a987be60..86c0d18a 100644
--- a/src/unix/internal.h
+++ b/src/unix/internal.h
@@ -293,6 +293,9 @@ int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb);
int uv__tcp_nodelay(int fd, int on);
int uv__tcp_keepalive(int fd, int on, unsigned int delay);
+/* tty */
+void uv__tty_close(uv_tty_t* handle);
+
/* pipe */
int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb);
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)