diff --git a/src/win/handle.c b/src/win/handle.c index cb60343d..b67139cb 100644 --- a/src/win/handle.c +++ b/src/win/handle.c @@ -105,6 +105,10 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) { } return; + case UV_TTY: + uv_tty_close((uv_tty_t*) handle); + return; + case UV_UDP: udp = (uv_udp_t*) handle; uv_udp_recv_stop(udp); @@ -184,6 +188,10 @@ void uv_process_endgames(uv_loop_t* loop) { uv_pipe_endgame(loop, (uv_pipe_t*) handle); break; + case UV_TTY: + uv_tty_endgame(loop, (uv_tty_t*) handle); + break; + case UV_UDP: uv_udp_endgame(loop, (uv_udp_t*) handle); break; diff --git a/src/win/internal.h b/src/win/internal.h index 457bb278..fa20e466 100644 --- a/src/win/internal.h +++ b/src/win/internal.h @@ -185,6 +185,7 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, int uv_tty_read_stop(uv_tty_t* handle); int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, uv_buf_t bufs[], int bufcnt, uv_write_cb cb); +void uv_tty_close(uv_tty_t* handle); void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req); @@ -197,6 +198,8 @@ void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, uv_connect_t* req); +void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle); + /* * Loop watchers diff --git a/src/win/tty.c b/src/win/tty.c index 34021e31..1a4bf11a 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -1481,6 +1481,12 @@ int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, uv_buf_t bufs[], int bufcnt, uv_write_cb cb) { DWORD error; + if ((handle->flags & UV_HANDLE_SHUTTING) || + (handle->flags & UV_HANDLE_CLOSING)) { + uv_set_sys_error(loop, WSAESHUTDOWN); + return -1; + } + uv_req_init(loop, (uv_req_t*) req); req->type = UV_WRITE; req->handle = (uv_stream_t*) handle; @@ -1523,6 +1529,54 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, } +void uv_tty_close(uv_tty_t* handle) { + uv_tty_read_stop(handle); + CloseHandle(handle->handle); + + if (handle->reqs_pending == 0) { + uv_want_endgame(handle->loop, (uv_handle_t*) handle); + } +} + + +void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { + if (handle->flags & UV_HANDLE_CONNECTION && + handle->flags & UV_HANDLE_SHUTTING && + !(handle->flags & UV_HANDLE_SHUT) && + handle->write_reqs_pending == 0) { + handle->flags |= UV_HANDLE_SHUT; + + /* TTY shutdown is really just a no-op */ + if (handle->shutdown_req->cb) { + handle->shutdown_req->cb(handle->shutdown_req, 0); + } + + DECREASE_PENDING_REQ_COUNT(handle); + return; + } + + if (handle->flags & UV_HANDLE_CLOSING && + handle->reqs_pending == 0) { + /* The console handle duplicate used for line reading should be destroyed */ + /* by uv_tty_read_stop. */ + assert(handle->read_line_handle == NULL); + + /* The wait handle used for raw reading should be unregistered when the */ + /* wait callback runs. */ + assert(handle->read_raw_wait == NULL); + + assert(!(handle->flags & UV_HANDLE_CLOSED)); + handle->flags |= UV_HANDLE_CLOSED; + + if (handle->close_cb) { + handle->close_cb((uv_handle_t*)handle); + } + + uv_unref(loop); + } +} + + /* TODO: remove me */ void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* raw_req) {