DLLEXPORT void jl_close_uv(uv_handle_t *handle) { if (!handle || uv_is_closing(handle)) return; if (handle->type==UV_TTY) uv_tty_set_mode((uv_tty_t*)handle,0); if ( (handle->type == UV_NAMED_PIPE || handle->type == UV_TCP) && uv_is_writable( (uv_stream_t *) handle)) { // Make sure that the stream has not already been marked closed in Julia. // A double shutdown would cause the process to hang on exit. JULIA_CB(isopen, handle->data, 0); if (!jl_is_int32(ret)) { jl_error("jl_close_uv: _uv_hook_isopen must return an int32."); } if (!jl_unbox_int32(ret)){ return; } uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t)); int err = uv_shutdown(req, (uv_stream_t*)handle, &shutdownCallback); if (err != 0) { printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop()))); uv_close(handle, &closeHandle); } } else { uv_close(handle,&closeHandle); } }
DLLEXPORT void jl_close_uv(uv_handle_t *handle) { if (handle->type==UV_TTY) uv_tty_set_mode((uv_tty_t*)handle,0); if ((handle->type == UV_NAMED_PIPE || handle->type == UV_TCP) && uv_is_writable((uv_stream_t*)handle)) { uv_shutdown_t *req = (uv_shutdown_t*)malloc(sizeof(uv_shutdown_t)); req->data = 0; /* * We are explicity ignoring the error here for the following reason: * There is only two scenarios in which this returns an error: * a) In case the stream is already shut down, in which case we're likely * in the process of closing this stream (since there's no other call to * uv_shutdown). * b) In case the stream is already closed, in which case uv_close would * cause an assertion failure. */ uv_shutdown(req, (uv_stream_t*)handle, &jl_uv_shutdownCallback); } else if (handle->type == UV_FILE) { uv_fs_t req; jl_uv_file_t *fd = (jl_uv_file_t*)handle; if (fd->file != -1) { uv_fs_close(handle->loop, &req, fd->file, NULL); fd->file = -1; } } else if (!uv_is_closing((uv_handle_t*)handle)) { uv_close(handle,&jl_uv_closeHandle); } }
static int couv_is_writable(lua_State *L) { uv_stream_t *handle; handle = couvL_checkudataclass(L, 1, COUV_STREAM_MTBL_NAME); lua_pushboolean(L, uv_is_writable(handle)); return 1; }
static PyObject * Stream_writable_get(Stream *self, void *closure) { UNUSED_ARG(closure); RAISE_IF_HANDLE_NOT_INITIALIZED(self, NULL); return PyBool_FromLong((long)uv_is_writable((uv_stream_t *)UV_HANDLE(self))); }
static void send_recv_start() { int r; ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx2.channel)); ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx2.channel)); ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx2.channel)); r = uv_read_start((uv_stream_t*)&ctx2.channel, alloc_cb, read_cb); ASSERT(r == 0); }
BOOL KUVSocket::Send(H_CONNECTION handle, LPSTR pData, UINT nDataLen) { BOOL bRet = false; g_ClearError(); // check if (handle < 1 || handle > m_nIdGen) { sprintf_s(g_ErrorMsg, "KUVSocket::Send Fail, the handle is Error : %d\n%s", handle,g_ErrorMsg); return bRet; } if (!pData) { sprintf_s(g_ErrorMsg, "KUVSocket::Send Fail, the send data is emtpy\n%s", g_ErrorMsg); return bRet; } uv_tcp_t* pTcp = getUVHandle(handle); if (!pTcp) { sprintf_s(g_ErrorMsg, "KUVSocket::Send Fail, can't get uv_tcp_t with handle : %d\n%s", handle, g_ErrorMsg); return bRet; } if (!uv_is_writable((uv_stream_t*)pTcp)) { sprintf_s(g_ErrorMsg, "KUVSocket::Send Fail,this pTcp is unable for writing: %d\n%s", handle, g_ErrorMsg); return bRet; } Header *pHeader = new Header(); pHeader->SetDataLen(nDataLen); SendReq* pSendReq = new SendReq(); pSendReq->pHeader = pHeader; uv_buf_t buff[2]; buff[0] = uv_buf_init((LPSTR)pHeader->GetHeader(), pHeader->GetHeaderSize()); buff[1] = uv_buf_init(pData, nDataLen); m_nError = uv_write(pSendReq, (uv_stream_t*)pTcp, buff, 2, OnConnectionWriteCompleted); if (m_nError != 0) { delete pHeader; delete pSendReq; sprintf_s(g_ErrorMsg, "KUVSocket::Send Fail, uv_write get UV Error Code: %d\n%s", m_nError, g_ErrorMsg); return bRet; } bRet = TRUE; return bRet; }
DLLEXPORT void uv_atexit_hook() { uv_loop_t* loop = jl_global_event_loop(); struct uv_shutdown_queue queue = {NULL, NULL}; uv_walk(loop, jl_uv_exitcleanup_walk, &queue); struct uv_shutdown_queue_item *item = queue.first; while (item) { uv_handle_t *handle = item->h; switch(handle->type) { case UV_TTY: case UV_UDP: //#ifndef __WIN32__ // unix only supports shutdown on TCP and NAMED_PIPE // but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general uv_close(handle,NULL); break; //#endif case UV_TCP: case UV_NAMED_PIPE: if (uv_is_writable((uv_stream_t*)handle)) { // uv_shutdown returns an error if not writable uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t)); int err = uv_shutdown(req, (uv_stream_t*)handle, jl_shutdown_uv_cb); if (err != 0) { printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop())));} } else { uv_close(handle,NULL); } break; case UV_POLL: case UV_TIMER: case UV_PREPARE: case UV_CHECK: case UV_IDLE: case UV_ASYNC: case UV_SIGNAL: case UV_PROCESS: case UV_FS_EVENT: case UV_FS_POLL: uv_close(handle,NULL); //do we want to use jl_close_uv? break; case UV_HANDLE: case UV_STREAM: case UV_UNKNOWN_HANDLE: case UV_HANDLE_TYPE_MAX: case UV_RAW_FD: case UV_RAW_HANDLE: default: assert(0); } item = item->next; } uv_run(loop); //let libuv spin until everything has finished closing }
JL_DLLEXPORT void jl_close_uv(uv_handle_t *handle) { if (handle->type == UV_FILE) { uv_fs_t req; jl_uv_file_t *fd = (jl_uv_file_t*)handle; if (fd->file != -1) { uv_fs_close(handle->loop, &req, fd->file, NULL); fd->file = -1; } jl_uv_closeHandle(handle); // synchronous (ok since the callback is known to not interact with any global state) return; } if (handle->type == UV_NAMED_PIPE || handle->type == UV_TCP) { #ifdef _OS_WINDOWS_ if (((uv_stream_t*)handle)->stream.conn.shutdown_req) { #else if (((uv_stream_t*)handle)->shutdown_req) { #endif // don't close the stream while attempting a graceful shutdown return; } if (uv_is_writable((uv_stream_t*)handle)) { // attempt graceful shutdown of writable streams to give them a chance to flush first uv_shutdown_t *req = (uv_shutdown_t*)malloc(sizeof(uv_shutdown_t)); req->data = 0; /* * We are explicitly ignoring the error here for the following reason: * There is only two scenarios in which this returns an error: * a) In case the stream is already shut down, in which case we're likely * in the process of closing this stream (since there's no other call to * uv_shutdown). * b) In case the stream is already closed, in which case uv_close would * cause an assertion failure. */ uv_shutdown(req, (uv_stream_t*)handle, &jl_uv_shutdownCallback); return; } } if (!uv_is_closing((uv_handle_t*)handle)) { // avoid double-closing the stream if (handle->type == UV_TTY) uv_tty_set_mode((uv_tty_t*)handle, UV_TTY_MODE_NORMAL); uv_close(handle, &jl_uv_closeHandle); } } JL_DLLEXPORT void jl_forceclose_uv(uv_handle_t *handle) { uv_close(handle,&jl_uv_closeHandle); }
int ipc_helper(int listen_after_write) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. */ struct sockaddr_in addr; uv_write_t write_req; int r; uv_buf_t buf; uv_os_fd_t stdin_handle = uv_convert_fd_to_handle(0); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, stdin_handle); ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); if (!listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection); ASSERT(r == 0); } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); if (listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection); ASSERT(r == 0); } r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); ASSERT(connection_accepted == 1); ASSERT(close_cb_called == 3); MAKE_VALGRIND_HAPPY(); return 0; }
int ipc_helper_tcp_connection(void) { /* * This is launched from test-ipc.c. stdin is a duplex channel * over which a handle will be transmitted. */ int r; struct sockaddr_in addr; uv_os_fd_t stdin_handle = uv_convert_fd_to_handle(0); r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, stdin_handle); ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); r = uv_listen((uv_stream_t*)&tcp_server, BACKLOG, ipc_on_connection_tcp_conn); ASSERT(r == 0); /* Make a connection to the server */ r = uv_tcp_init(uv_default_loop(), &conn.conn); ASSERT(r == 0); ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr)); r = uv_tcp_connect(&conn.conn_req, (uv_tcp_t*) &conn.conn, (const struct sockaddr*) &addr, connect_child_process_cb); ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); ASSERT(tcp_conn_read_cb_called == 1); ASSERT(tcp_conn_write_cb_called == 1); ASSERT(close_cb_called == 4); MAKE_VALGRIND_HAPPY(); return 0; }
int ipc_helper_closed_handle(void) { int r; struct sockaddr_in addr; uv_write_t write_req; uv_write_t write_req2; uv_buf_t buf; char buffer[LARGE_SIZE]; r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, 0); ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); memset(buffer, '.', LARGE_SIZE); buf = uv_buf_init(buffer, LARGE_SIZE); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); r = uv_write(&write_req, (uv_stream_t*)&channel, &buf, 1, closed_handle_large_write_cb); ASSERT(r == 0); r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, closed_handle_write_cb); ASSERT(r == 0); uv_close((uv_handle_t*)&tcp_server, NULL); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; }
int ipc_helper(int listen_after_write) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. */ uv_write_t write_req; int r; uv_buf_t buf; r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, 0); ASSERT(uv_is_readable((uv_stream_t*) &channel)); ASSERT(uv_is_writable((uv_stream_t*) &channel)); ASSERT(!uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, uv_ip4_addr("0.0.0.0", TEST_PORT)); ASSERT(r == 0); if (!listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); if (listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } r = uv_run(uv_default_loop()); ASSERT(r == 0); ASSERT(connection_accepted == 1); ASSERT(close_cb_called == 3); MAKE_VALGRIND_HAPPY(); return 0; }
static int ipc_helper(int listen_after_write) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. In this initial version only * data is transfered over the channel. XXX edit this comment after handle * transfer is added. */ uv_write_t write_req; int r; uv_buf_t buf; r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, 0); ASSERT(uv_is_readable(&channel)); ASSERT(uv_is_writable(&channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, uv_ip4_addr("0.0.0.0", TEST_PORT)); ASSERT(r == 0); if (!listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); if (listen_after_write) { r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); ASSERT(r == 0); } r = uv_run(uv_default_loop()); ASSERT(r == 0); ASSERT(connection_accepted == 1); ASSERT(close_cb_called == 3); return 0; }
static void pinger_on_connect(uv_connect_t *req, int status) { pinger_t *pinger = (pinger_t*)req->handle->data; pinger_on_connect_count++; ASSERT(status == 0); ASSERT(uv_is_readable(req->handle)); ASSERT(uv_is_writable(req->handle)); ASSERT(!uv_is_closing((uv_handle_t *)req->handle)); pinger_write_ping(pinger); uv_read_start((uv_stream_t*)(req->handle), alloc_cb, pinger_read_cb); }
int ipc_helper_bind_twice(void) { /* * This is launched from test-ipc.c. stdin is a duplex channel * over which two handles will be transmitted. */ struct sockaddr_in addr; uv_write_t write_req; uv_write_t write_req2; int r; uv_buf_t buf; uv_os_fd_t stdin_handle = uv_convert_fd_to_handle(0); ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, stdin_handle); ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); buf = uv_buf_init("hello\n", 6); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_init(uv_default_loop(), &tcp_server2); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server2, (const struct sockaddr*) &addr, 0); ASSERT(r == 0); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); r = uv_write2(&write_req2, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server2, NULL); ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; }
int ipc_helper_tcp_connection() { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. */ int r; struct sockaddr_in addr; r = uv_pipe_init(uv_default_loop(), &channel, 1); ASSERT(r == 0); uv_pipe_open(&channel, 0); ASSERT(uv_is_readable((uv_stream_t*)&channel)); ASSERT(uv_is_writable((uv_stream_t*)&channel)); ASSERT(!uv_is_closing((uv_handle_t*)&channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); r = uv_tcp_bind(&tcp_server, uv_ip4_addr("0.0.0.0", TEST_PORT)); ASSERT(r == 0); r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection_tcp_conn); ASSERT(r == 0); /* Make a connection to the server */ r = uv_tcp_init(uv_default_loop(), &conn.conn); ASSERT(r == 0); addr = uv_ip4_addr("127.0.0.1", TEST_PORT); r = uv_tcp_connect(&conn.conn_req, (uv_tcp_t*)&conn.conn, addr, connect_child_process_cb); ASSERT(r == 0); r = uv_run(uv_default_loop()); ASSERT(r == 0); ASSERT(tcp_conn_read_cb_called == 1); ASSERT(tcp_conn_write_cb_called == 1); ASSERT(close_cb_called == 4); MAKE_VALGRIND_HAPPY(); return 0; }
int64_t Client::send(size_t size) { LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf); if (state() != ConnectedState || !uv_is_writable(m_stream)) { LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state); return -1; } uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size); if (uv_try_write(m_stream, &buf, 1) < 0) { close(); return -1; } m_expire = uv_now(uv_default_loop()) + kResponseTimeout; return m_sequence++; }
DLLEXPORT void jl_close_uv(uv_handle_t *handle) { if (handle->type==UV_TTY) uv_tty_set_mode((uv_tty_t*)handle,0); if ((handle->type == UV_NAMED_PIPE || handle->type == UV_TCP) && uv_is_writable((uv_stream_t*)handle)) { // Make sure that the stream has not already been marked closed in Julia. // A double shutdown would cause the process to hang on exit. if (handle->data) { JULIA_CB(isopen, handle->data, 0); if (!jl_is_int32(ret)) { jl_error("jl_close_uv: _uv_hook_isopen must return an int32."); } if (!jl_unbox_int32(ret)){ return; } } uv_shutdown_t *req = (uv_shutdown_t*)malloc(sizeof(uv_shutdown_t)); req->data = 0; /* * We are explicity ignoring the error here for the following reason: * There is only two scenarios in which this returns an error: * a) In case the stream is already shut down, in which case we're likely * in the process of closing this stream (since there's no other call to * uv_shutdown). * b) In case the stream is already closed, in which case uv_close would * cause an assertion failure. */ uv_shutdown(req, (uv_stream_t*)handle, &jl_uv_shutdownCallback); } else if (handle->type == UV_FILE) { uv_fs_t req; jl_uv_file_t *fd = (jl_uv_file_t*)handle; if (fd->file != -1) { uv_fs_close(handle->loop, &req, fd->file, NULL); fd->file = -1; } } else if (!uv_is_closing((uv_handle_t*)handle)) { uv_close(handle,&jl_uv_closeHandle); } }
void durotanReply(itemQuery* query, char* reply, int n) { if(uv_is_closing((uv_handle_t*) query->client) || !uv_is_writable(query->client)) { return; } // Allocate space for the message, a comma, the key, a comma, the stats, a newline, and a null character. int len = 1 + 1 + strlen(query->key) + 1 + n + 2; uv_buf_t* buf = malloc(sizeof(uv_buf_t)); buf->base = malloc(len * sizeof(char)); buf->len = len - 1; // Format the message snprintf(buf->base, len, "%d,%s,%s\n", MSG_ITEM, query->key, reply); // Create write request uv_write_t* req = (uv_write_t*)malloc(sizeof(uv_write_t)); req->data = (void*)buf; // Send her off uv_write(req, query->client, buf, 1, durotanOnWrite); }
/* stdin is a duplex channel over which a handle is sent. * We receive it and send it back where it came from. */ int ipc_send_recv_helper(void) { int r; memset(&ctx, 0, sizeof(ctx)); r = uv_pipe_init(uv_default_loop(), &ctx.channel, 1); ASSERT(r == 0); uv_pipe_open(&ctx.channel, 0); ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx.channel)); ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx.channel)); ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx.channel)); r = uv_read2_start((uv_stream_t*)&ctx.channel, alloc_cb, read2_cb); ASSERT(r == 0); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); MAKE_VALGRIND_HAPPY(); return 0; }
DLLEXPORT void uv_atexit_hook() { #if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS) jl_print_gc_stats(JL_STDERR); #endif if (jl_base_module) { jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); if (f!=NULL && jl_is_function(f)) { jl_apply((jl_function_t*)f, NULL, 0); } } uv_loop_t* loop = jl_global_event_loop(); struct uv_shutdown_queue queue = {NULL, NULL}; uv_walk(loop, jl_uv_exitcleanup_walk, &queue); // close stdout and stderr last, since we like being // able to show stuff (incl. printf's) jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stdout, &queue); jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stderr, &queue); struct uv_shutdown_queue_item *item = queue.first; while (item) { uv_handle_t *handle = item->h; if (uv_is_closing(handle)) { item = item->next; continue; } switch(handle->type) { case UV_TTY: case UV_UDP: //#ifndef __WIN32__ // unix only supports shutdown on TCP and NAMED_PIPE // but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general jl_close_uv(handle); break; //#endif case UV_TCP: case UV_NAMED_PIPE: if (uv_is_writable((uv_stream_t*)handle)) { // uv_shutdown returns an error if not writable uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t)); int err = uv_shutdown(req, (uv_stream_t*)handle, jl_shutdown_uv_cb); if (err != 0) { printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop()))); jl_close_uv(handle); } } else { jl_close_uv(handle); } break; case UV_POLL: case UV_TIMER: case UV_PREPARE: case UV_CHECK: case UV_IDLE: case UV_ASYNC: case UV_SIGNAL: case UV_PROCESS: case UV_FS_EVENT: case UV_FS_POLL: jl_close_uv(handle); break; case UV_HANDLE: case UV_STREAM: case UV_UNKNOWN_HANDLE: case UV_HANDLE_TYPE_MAX: case UV_RAW_FD: case UV_RAW_HANDLE: default: assert(0); } item = item->next; } uv_run(loop,UV_RUN_DEFAULT); //let libuv spin until everything has finished closing }
void uv__stream_osx_select(void* arg) { uv_stream_t* stream; uv__stream_select_t* s; char buf[1024]; fd_set sread; fd_set swrite; fd_set serror; int events; int fd; int r; int max_fd; stream = arg; s = stream->select; fd = stream->io_watcher.fd; if (fd > s->int_fd) max_fd = fd; else max_fd = s->int_fd; while (1) { /* Terminate on semaphore */ if (uv_sem_trywait(&s->sem) == 0) break; /* Watch fd using select(2) */ FD_ZERO(&sread); FD_ZERO(&swrite); FD_ZERO(&serror); if (uv_is_readable(stream)) FD_SET(fd, &sread); if (uv_is_writable(stream)) FD_SET(fd, &swrite); FD_SET(fd, &serror); FD_SET(s->int_fd, &sread); /* Wait indefinitely for fd events */ r = select(max_fd + 1, &sread, &swrite, &serror, NULL); if (r == -1) { if (errno == EINTR) continue; /* XXX: Possible?! */ abort(); } /* Ignore timeouts */ if (r == 0) continue; /* Empty socketpair's buffer in case of interruption */ if (FD_ISSET(s->int_fd, &sread)) while (1) { r = read(s->int_fd, buf, sizeof(buf)); if (r == sizeof(buf)) continue; if (r != -1) break; if (errno == EAGAIN || errno == EWOULDBLOCK) break; if (errno == EINTR) continue; abort(); } /* Handle events */ events = 0; if (FD_ISSET(fd, &sread)) events |= UV__POLLIN; if (FD_ISSET(fd, &swrite)) events |= UV__POLLOUT; if (FD_ISSET(fd, &serror)) events |= UV__POLLERR; uv_mutex_lock(&s->mutex); s->events |= events; uv_mutex_unlock(&s->mutex); if (events != 0) uv_async_send(&s->async); } }
static int luv_stream_writable(lua_State* L) { luv_object_t* self = (luv_object_t*)lua_touserdata(L, 1); lua_pushboolean(L, uv_is_writable(&self->h.stream)); return 1; }
void uv__stream_osx_select(void* arg) { uv_stream_t* stream; uv__stream_select_t* s; fd_set read; fd_set write; fd_set error; struct timeval timeout; int events; int fd; int r; int max_fd; stream = arg; s = stream->select; fd = stream->io_watcher.fd; if (fd > s->int_fd) max_fd = fd; else max_fd = s->int_fd; while (1) { /* Terminate on semaphore */ if (uv_sem_trywait(&s->sem) == 0) break; /* Watch fd using select(2) */ FD_ZERO(&read); FD_ZERO(&write); FD_ZERO(&error); if (uv_is_readable(stream)) FD_SET(fd, &read); if (uv_is_writable(stream)) FD_SET(fd, &write); FD_SET(fd, &error); FD_SET(s->int_fd, &read); timeout.tv_sec = 0; timeout.tv_usec = 250000; /* 250 ms timeout */ r = select(max_fd + 1, &read, &write, &error, &timeout); if (r == -1) { if (errno == EINTR) continue; /* XXX: Possible?! */ abort(); } /* Ignore timeouts */ if (r == 0) continue; /* Handle events */ events = 0; if (FD_ISSET(fd, &read)) events |= UV__POLLIN; if (FD_ISSET(fd, &write)) events |= UV__POLLOUT; if (FD_ISSET(fd, &error)) events |= UV__POLLERR; uv_mutex_lock(&s->mutex); s->events |= events; uv_mutex_unlock(&s->mutex); if (events != 0) uv_async_send(&s->async); } }
static int luv_is_writable(lua_State* L) { uv_stream_t* handle = luv_check_stream(L, 1); lua_pushboolean(L, uv_is_writable(handle)); return 1; }
static void uv__stream_osx_select(void* arg) { uv_stream_t* stream; uv__stream_select_t* s; char buf[1024]; fd_set sread; fd_set swrite; int events; int fd; int r; int max_fd; stream = arg; s = stream->select; fd = s->fd; if (fd > s->int_fd) max_fd = fd; else max_fd = s->int_fd; while (1) { /* Terminate on semaphore */ if (uv_sem_trywait(&s->close_sem) == 0) break; /* Watch fd using select(2) */ FD_ZERO(&sread); FD_ZERO(&swrite); if (uv_is_readable(stream)) FD_SET(fd, &sread); if (uv_is_writable(stream)) FD_SET(fd, &swrite); FD_SET(s->int_fd, &sread); /* Wait indefinitely for fd events */ r = select(max_fd + 1, &sread, &swrite, NULL, NULL); if (r == -1) { if (errno == EINTR) continue; /* XXX: Possible?! */ abort(); } /* Ignore timeouts */ if (r == 0) continue; /* Empty socketpair's buffer in case of interruption */ if (FD_ISSET(s->int_fd, &sread)) while (1) { r = read(s->int_fd, buf, sizeof(buf)); if (r == sizeof(buf)) continue; if (r != -1) break; if (errno == EAGAIN || errno == EWOULDBLOCK) break; if (errno == EINTR) continue; abort(); } /* Handle events */ events = 0; if (FD_ISSET(fd, &sread)) events |= UV__POLLIN; if (FD_ISSET(fd, &swrite)) events |= UV__POLLOUT; assert(events != 0 || FD_ISSET(s->int_fd, &sread)); if (events != 0) { ACCESS_ONCE(int, s->events) = events; uv_async_send(&s->async); uv_sem_wait(&s->async_sem); /* Should be processed at this stage */ assert((s->events == 0) || (stream->flags & UV_CLOSING)); } }