diff --git a/include/uv.h b/include/uv.h index 2ee7c315..2e39d08a 100644 --- a/include/uv.h +++ b/include/uv.h @@ -228,6 +228,10 @@ int uv_is_active(uv_handle_t* handle); /* * Request handle to be closed. close_cb will be called asynchronously after * this call. This MUST be called on each handle before memory is released. + * + * Note that handles that wrap file descriptors are closed immediately but + * close_cb will still be deferred to the next iteration of the event loop. + * It gives you a chance to free up any resources associated with the handle. */ void uv_close(uv_handle_t* handle, uv_close_cb close_cb); diff --git a/src/uv-unix.c b/src/uv-unix.c index a57a30b9..6fa51e72 100644 --- a/src/uv-unix.c +++ b/src/uv-unix.c @@ -199,19 +199,31 @@ static uv_err_t uv_err_new(uv_handle_t* handle, int sys_error) { void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { - uv_tcp_t* tcp; - uv_pipe_t* pipe; uv_async_t* async; uv_timer_t* timer; + uv_stream_t* stream; uv_process_t* process; handle->close_cb = close_cb; switch (handle->type) { + case UV_NAMED_PIPE: + uv_pipe_cleanup((uv_pipe_t*)handle); + /* Fall through. */ + case UV_TCP: - tcp = (uv_tcp_t*) handle; - uv_read_stop((uv_stream_t*)tcp); - ev_io_stop(EV_DEFAULT_ &tcp->write_watcher); + stream = (uv_stream_t*)handle; + + uv_read_stop(stream); + ev_io_stop(EV_DEFAULT_ &stream->write_watcher); + + uv__close(stream->fd); + stream->fd = -1; + + if (stream->accepted_fd >= 0) { + uv__close(stream->accepted_fd); + stream->accepted_fd = -1; + } break; case UV_PREPARE: @@ -240,13 +252,6 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { ev_timer_stop(EV_DEFAULT_ &timer->timer_watcher); break; - case UV_NAMED_PIPE: - pipe = (uv_pipe_t*)handle; - uv_pipe_cleanup(pipe); - uv_read_stop((uv_stream_t*)handle); - ev_io_stop(EV_DEFAULT_ &pipe->write_watcher); - break; - case UV_PROCESS: process = (uv_process_t*)handle; ev_child_stop(EV_DEFAULT_UC_ &process->child_watcher); @@ -574,23 +579,9 @@ void uv__finish_close(uv_handle_t* handle) { case UV_NAMED_PIPE: case UV_TCP: - { - uv_stream_t* stream; - - stream = (uv_stream_t*)handle; - - assert(!ev_is_active(&stream->read_watcher)); - assert(!ev_is_active(&stream->write_watcher)); - - uv__close(stream->fd); - stream->fd = -1; - - if (stream->accepted_fd >= 0) { - uv__close(stream->accepted_fd); - stream->accepted_fd = -1; - } + assert(!ev_is_active(&((uv_stream_t*)handle)->read_watcher)); + assert(!ev_is_active(&((uv_stream_t*)handle)->write_watcher)); break; - } case UV_PROCESS: assert(!ev_is_active(&((uv_process_t*)handle)->child_watcher));