static void uv__drain(uv_handle_t* handle) { assert(!uv_write_queue_head(handle)); assert(handle->write_queue_size == 0); ev_io_stop(EV_DEFAULT_ &handle->write_watcher); /* Shutdown? */ if (uv_flag_is_set(handle, UV_SHUTTING) && !uv_flag_is_set(handle, UV_CLOSING) && !uv_flag_is_set(handle, UV_SHUT)) { assert(handle->shutdown_req); uv_req_t* req = handle->shutdown_req; uv_shutdown_cb cb = req->cb; if (shutdown(handle->fd, SHUT_WR)) { /* Error. Nothing we can do, close the handle. */ uv_err_new(handle, errno); uv_close(handle); if (cb) cb(req, -1); } else { uv_err_new(handle, 0); uv_flag_set(handle, UV_SHUT); if (cb) cb(req, 0); } } }
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { uv_tcp_t* tcp = (uv_tcp_t*)handle; assert(handle->type == UV_TCP && "uv_shutdown (unix) only supports uv_tcp_t right now"); assert(tcp->fd >= 0); /* Initialize request */ uv__req_init((uv_req_t*)req); req->handle = handle; req->cb = cb; if (uv_flag_is_set((uv_handle_t*)tcp, UV_SHUT) || uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSED) || uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING)) { return -1; } tcp->shutdown_req = req; req->type = UV_SHUTDOWN; uv_flag_set((uv_handle_t*)tcp, UV_SHUTTING); ev_io_start(EV_DEFAULT_UC_ &tcp->write_watcher); return 0; }
static void uv__drain(uv_tcp_t* tcp) { uv_shutdown_t* req; assert(!uv_write_queue_head(tcp)); assert(tcp->write_queue_size == 0); ev_io_stop(EV_DEFAULT_ &tcp->write_watcher); /* Shutdown? */ if (uv_flag_is_set((uv_handle_t*)tcp, UV_SHUTTING) && !uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING) && !uv_flag_is_set((uv_handle_t*)tcp, UV_SHUT)) { assert(tcp->shutdown_req); req = tcp->shutdown_req; if (shutdown(tcp->fd, SHUT_WR)) { /* Error. Report it. User should call uv_close(). */ uv_err_new((uv_handle_t*)tcp, errno); if (req->cb) { req->cb(req, -1); } } else { uv_err_new((uv_handle_t*)tcp, 0); uv_flag_set((uv_handle_t*)tcp, UV_SHUT); if (req->cb) { req->cb(req, 0); } } } }
int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb) { uv_tcp_t* tcp = (uv_tcp_t*)stream; /* The UV_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. */ uv_flag_set((uv_handle_t*)tcp, UV_READING); /* TODO: try to do the read inline? */ /* TODO: keep track of tcp state. If we've gotten a EOF then we should * not start the IO watcher. */ assert(tcp->fd >= 0); assert(alloc_cb); tcp->read_cb = read_cb; tcp->alloc_cb = alloc_cb; /* These should have been set by uv_tcp_init. */ assert(tcp->read_watcher.data == tcp); assert(tcp->read_watcher.cb == uv__tcp_io); ev_io_start(EV_DEFAULT_UC_ &tcp->read_watcher); return 0; }
void uv__finish_close(uv_handle_t* handle) { assert(uv_flag_is_set(handle, UV_CLOSING)); assert(!uv_flag_is_set(handle, UV_CLOSED)); uv_flag_set(handle, UV_CLOSED); switch (handle->type) { case UV_TCP: /* XXX Is it necessary to stop these watchers here? weren't they * supposed to be stopped in uv_close()? */ ev_io_stop(EV_DEFAULT_ &handle->write_watcher); ev_io_stop(EV_DEFAULT_ &handle->read_watcher); assert(!ev_is_active(&handle->read_watcher)); assert(!ev_is_active(&handle->write_watcher)); close(handle->fd); handle->fd = -1; if (handle->accepted_fd >= 0) { close(handle->accepted_fd); handle->accepted_fd = -1; } break; case UV_PREPARE: assert(!ev_is_active(&handle->prepare_watcher)); break; case UV_CHECK: assert(!ev_is_active(&handle->check_watcher)); break; case UV_IDLE: assert(!ev_is_active(&handle->idle_watcher)); break; case UV_ASYNC: assert(!ev_is_active(&handle->async_watcher)); break; case UV_TIMER: assert(!ev_is_active(&handle->timer_watcher)); break; default: assert(0); break; } ev_idle_stop(EV_DEFAULT_ &handle->next_watcher); if (handle->close_cb) { handle->close_cb(handle, 0); } ev_unref(EV_DEFAULT_UC); }
int uv_close(uv_handle_t* handle, uv_close_cb close_cb) { uv_tcp_t* tcp; uv_async_t* async; uv_timer_t* timer; handle->close_cb = close_cb; switch (handle->type) { case UV_TCP: tcp = (uv_tcp_t*) handle; uv_read_stop((uv_stream_t*)tcp); ev_io_stop(EV_DEFAULT_ &tcp->write_watcher); break; case UV_PREPARE: uv_prepare_stop((uv_prepare_t*) handle); break; case UV_CHECK: uv_check_stop((uv_check_t*) handle); break; case UV_IDLE: uv_idle_stop((uv_idle_t*) handle); break; case UV_ASYNC: async = (uv_async_t*)handle; ev_async_stop(EV_DEFAULT_ &async->async_watcher); ev_ref(EV_DEFAULT_UC); break; case UV_TIMER: timer = (uv_timer_t*)handle; if (ev_is_active(&timer->timer_watcher)) { ev_ref(EV_DEFAULT_UC); } ev_timer_stop(EV_DEFAULT_ &timer->timer_watcher); break; default: assert(0); return -1; } uv_flag_set(handle, UV_CLOSING); /* This is used to call the on_close callback in the next loop. */ ev_idle_start(EV_DEFAULT_ &handle->next_watcher); ev_feed_event(EV_DEFAULT_ &handle->next_watcher, EV_IDLE); assert(ev_is_pending(&handle->next_watcher)); return 0; }
int uv_close(uv_handle_t* handle) { switch (handle->type) { case UV_TCP: ev_io_stop(EV_DEFAULT_ &handle->write_watcher); ev_io_stop(EV_DEFAULT_ &handle->read_watcher); break; case UV_PREPARE: uv_prepare_stop(handle); break; case UV_CHECK: uv_check_stop(handle); break; case UV_IDLE: uv_idle_stop(handle); break; case UV_ASYNC: ev_async_stop(EV_DEFAULT_ &handle->async_watcher); ev_ref(EV_DEFAULT_UC); break; case UV_TIMER: if (ev_is_active(&handle->timer_watcher)) { ev_ref(EV_DEFAULT_UC); } ev_timer_stop(EV_DEFAULT_ &handle->timer_watcher); break; default: assert(0); return -1; } uv_flag_set(handle, UV_CLOSING); /* This is used to call the on_close callback in the next loop. */ ev_idle_start(EV_DEFAULT_ &handle->next_watcher); ev_feed_event(EV_DEFAULT_ &handle->next_watcher, EV_IDLE); assert(ev_is_pending(&handle->next_watcher)); return 0; }
int uv_shutdown(uv_req_t* req) { uv_handle_t* handle = req->handle; assert(handle->fd >= 0); if (uv_flag_is_set(handle, UV_SHUT) || uv_flag_is_set(handle, UV_CLOSED) || uv_flag_is_set(handle, UV_CLOSING)) { return -1; } handle->shutdown_req = req; req->type = UV_SHUTDOWN; uv_flag_set(handle, UV_SHUTTING); ev_io_start(EV_DEFAULT_UC_ &handle->write_watcher); return 0; }
int uv_read_start(uv_handle_t* handle, uv_read_cb cb) { /* The UV_READING flag is irrelevant of the state of the handle - it just * expresses the desired state of the user. */ uv_flag_set(handle, UV_READING); /* TODO: try to do the read inline? */ /* TODO: keep track of handle state. If we've gotten a EOF then we should * not start the IO watcher. */ assert(handle->fd >= 0); handle->read_cb = cb; /* These should have been set by uv_tcp_init. */ assert(handle->read_watcher.data == handle); assert(handle->read_watcher.cb == uv__tcp_io); ev_io_start(EV_DEFAULT_UC_ &handle->read_watcher); return 0; }
int uv_shutdown(uv_req_t* req) { uv_tcp_t* tcp = (uv_tcp_t*)req->handle; assert(tcp->fd >= 0); assert(tcp->type == UV_TCP); if (uv_flag_is_set((uv_handle_t*)tcp, UV_SHUT) || uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSED) || uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING)) { return -1; } tcp->shutdown_req = req; req->type = UV_SHUTDOWN; uv_flag_set((uv_handle_t*)tcp, UV_SHUTTING); ev_io_start(EV_DEFAULT_UC_ &tcp->write_watcher); return 0; }