mirror of https://github.com/lukechilds/node.git
Ben Noordhuis
13 years ago
45 changed files with 1564 additions and 679 deletions
@ -0,0 +1,150 @@ |
|||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to |
||||
|
* deal in the Software without restriction, including without limitation the |
||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
|
* sell copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
|
* IN THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#ifndef UV_WIN_HANDLE_INL_H_ |
||||
|
#define UV_WIN_HANDLE_INL_H_ |
||||
|
|
||||
|
#include <assert.h> |
||||
|
|
||||
|
#include "uv.h" |
||||
|
#include "internal.h" |
||||
|
|
||||
|
|
||||
|
#define DECREASE_ACTIVE_COUNT(loop, handle) \ |
||||
|
do { \ |
||||
|
if (--(handle)->activecnt == 0 && \ |
||||
|
!((handle)->flags & UV_HANDLE_CLOSING)) { \ |
||||
|
uv__handle_stop((handle)); \ |
||||
|
} \ |
||||
|
assert((handle)->activecnt >= 0); \ |
||||
|
} while (0) |
||||
|
|
||||
|
|
||||
|
#define INCREASE_ACTIVE_COUNT(loop, handle) \ |
||||
|
do { \ |
||||
|
if ((handle)->activecnt++ == 0) { \ |
||||
|
uv__handle_start((handle)); \ |
||||
|
} \ |
||||
|
assert((handle)->activecnt > 0); \ |
||||
|
} while (0) |
||||
|
|
||||
|
|
||||
|
#define DECREASE_PENDING_REQ_COUNT(handle) \ |
||||
|
do { \ |
||||
|
assert(handle->reqs_pending > 0); \ |
||||
|
handle->reqs_pending--; \ |
||||
|
\ |
||||
|
if (handle->flags & UV_HANDLE_CLOSING && \ |
||||
|
handle->reqs_pending == 0) { \ |
||||
|
uv_want_endgame(loop, (uv_handle_t*)handle); \ |
||||
|
} \ |
||||
|
} while (0) |
||||
|
|
||||
|
|
||||
|
#define uv__handle_close(handle) \ |
||||
|
do { \ |
||||
|
ngx_queue_remove(&(handle)->handle_queue); \ |
||||
|
(handle)->flags |= UV_HANDLE_CLOSED; \ |
||||
|
if ((handle)->close_cb) { \ |
||||
|
(handle)->close_cb((uv_handle_t*)(handle)); \ |
||||
|
} \ |
||||
|
} while (0) |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_handle_init(uv_loop_t* loop, uv_handle_t* handle) { |
||||
|
handle->loop = loop; |
||||
|
handle->flags = UV__HANDLE_REF; |
||||
|
ngx_queue_insert_tail(&loop->handle_queue, &handle->handle_queue); |
||||
|
|
||||
|
loop->counters.handle_init++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) { |
||||
|
if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) { |
||||
|
handle->flags |= UV_HANDLE_ENDGAME_QUEUED; |
||||
|
|
||||
|
handle->endgame_next = loop->endgame_handles; |
||||
|
loop->endgame_handles = handle; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_process_endgames(uv_loop_t* loop) { |
||||
|
uv_handle_t* handle; |
||||
|
|
||||
|
while (loop->endgame_handles) { |
||||
|
handle = loop->endgame_handles; |
||||
|
loop->endgame_handles = handle->endgame_next; |
||||
|
|
||||
|
handle->flags &= ~UV_HANDLE_ENDGAME_QUEUED; |
||||
|
|
||||
|
switch (handle->type) { |
||||
|
case UV_TCP: |
||||
|
uv_tcp_endgame(loop, (uv_tcp_t*) handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_NAMED_PIPE: |
||||
|
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; |
||||
|
|
||||
|
case UV_POLL: |
||||
|
uv_poll_endgame(loop, (uv_poll_t*) handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_TIMER: |
||||
|
uv_timer_endgame(loop, (uv_timer_t*) handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_PREPARE: |
||||
|
case UV_CHECK: |
||||
|
case UV_IDLE: |
||||
|
uv_loop_watcher_endgame(loop, handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_ASYNC: |
||||
|
uv_async_endgame(loop, (uv_async_t*) handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_PROCESS: |
||||
|
uv_process_endgame(loop, (uv_process_t*) handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_FS_EVENT: |
||||
|
uv_fs_event_endgame(loop, (uv_fs_event_t*) handle); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
assert(0); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif /* UV_WIN_HANDLE_INL_H_ */ |
@ -0,0 +1,225 @@ |
|||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to |
||||
|
* deal in the Software without restriction, including without limitation the |
||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
|
* sell copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
|
* IN THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#ifndef UV_WIN_REQ_INL_H_ |
||||
|
#define UV_WIN_REQ_INL_H_ |
||||
|
|
||||
|
#include <assert.h> |
||||
|
|
||||
|
#include "uv.h" |
||||
|
#include "internal.h" |
||||
|
|
||||
|
|
||||
|
#define SET_REQ_STATUS(req, status) \ |
||||
|
(req)->overlapped.Internal = (ULONG_PTR) (status) |
||||
|
|
||||
|
#define SET_REQ_ERROR(req, error) \ |
||||
|
SET_REQ_STATUS((req), NTSTATUS_FROM_WIN32((error))) |
||||
|
|
||||
|
#define SET_REQ_SUCCESS(req) \ |
||||
|
SET_REQ_STATUS((req), STATUS_SUCCESS) |
||||
|
|
||||
|
#define GET_REQ_STATUS(req) \ |
||||
|
((NTSTATUS) (req)->overlapped.Internal) |
||||
|
|
||||
|
#define REQ_SUCCESS(req) \ |
||||
|
(NT_SUCCESS(GET_REQ_STATUS((req)))) |
||||
|
|
||||
|
#define GET_REQ_ERROR(req) \ |
||||
|
(pRtlNtStatusToDosError(GET_REQ_STATUS((req)))) |
||||
|
|
||||
|
#define GET_REQ_SOCK_ERROR(req) \ |
||||
|
(uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req)))) |
||||
|
|
||||
|
|
||||
|
#define REGISTER_HANDLE_REQ(loop, handle, req) \ |
||||
|
do { \ |
||||
|
INCREASE_ACTIVE_COUNT((loop), (handle)); \ |
||||
|
uv__req_register((loop), (req)); \ |
||||
|
} while (0) |
||||
|
|
||||
|
#define UNREGISTER_HANDLE_REQ(loop, handle, req) \ |
||||
|
do { \ |
||||
|
DECREASE_ACTIVE_COUNT((loop), (handle)); \ |
||||
|
uv__req_unregister((loop), (req)); \ |
||||
|
} while (0) |
||||
|
|
||||
|
|
||||
|
#define UV_SUCCEEDED_WITHOUT_IOCP(result) \ |
||||
|
((result) && (handle->flags & UV_HANDLE_SYNC_BYPASS_IOCP)) |
||||
|
|
||||
|
#define UV_SUCCEEDED_WITH_IOCP(result) \ |
||||
|
((result) || (GetLastError() == ERROR_IO_PENDING)) |
||||
|
|
||||
|
|
||||
|
#define POST_COMPLETION_FOR_REQ(loop, req) \ |
||||
|
if (!PostQueuedCompletionStatus((loop)->iocp, \ |
||||
|
0, \ |
||||
|
0, \ |
||||
|
&((req)->overlapped))) { \ |
||||
|
uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); \ |
||||
|
} |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_req_init(uv_loop_t* loop, uv_req_t* req) { |
||||
|
loop->counters.req_init++; |
||||
|
req->type = UV_UNKNOWN_REQ; |
||||
|
SET_REQ_SUCCESS(req); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { |
||||
|
return CONTAINING_RECORD(overlapped, uv_req_t, overlapped); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { |
||||
|
req->next_req = NULL; |
||||
|
if (loop->pending_reqs_tail) { |
||||
|
req->next_req = loop->pending_reqs_tail->next_req; |
||||
|
loop->pending_reqs_tail->next_req = req; |
||||
|
loop->pending_reqs_tail = req; |
||||
|
} else { |
||||
|
req->next_req = req; |
||||
|
loop->pending_reqs_tail = req; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#define DELEGATE_STREAM_REQ(loop, req, method, handle_at) \ |
||||
|
do { \ |
||||
|
switch (((uv_handle_t*) (req)->handle_at)->type) { \ |
||||
|
case UV_TCP: \ |
||||
|
uv_process_tcp_##method##_req(loop, \ |
||||
|
(uv_tcp_t*) ((req)->handle_at), \ |
||||
|
req); \ |
||||
|
break; \ |
||||
|
\ |
||||
|
case UV_NAMED_PIPE: \ |
||||
|
uv_process_pipe_##method##_req(loop, \ |
||||
|
(uv_pipe_t*) ((req)->handle_at), \ |
||||
|
req); \ |
||||
|
break; \ |
||||
|
\ |
||||
|
case UV_TTY: \ |
||||
|
uv_process_tty_##method##_req(loop, \ |
||||
|
(uv_tty_t*) ((req)->handle_at), \ |
||||
|
req); \ |
||||
|
break; \ |
||||
|
\ |
||||
|
default: \ |
||||
|
assert(0); \ |
||||
|
} \ |
||||
|
} while (0) |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_process_reqs(uv_loop_t* loop) { |
||||
|
uv_req_t* req; |
||||
|
uv_req_t* first; |
||||
|
uv_req_t* next; |
||||
|
|
||||
|
if (loop->pending_reqs_tail == NULL) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
first = loop->pending_reqs_tail->next_req; |
||||
|
next = first; |
||||
|
loop->pending_reqs_tail = NULL; |
||||
|
|
||||
|
while (next != NULL) { |
||||
|
req = next; |
||||
|
next = req->next_req != first ? req->next_req : NULL; |
||||
|
|
||||
|
switch (req->type) { |
||||
|
case UV_READ: |
||||
|
DELEGATE_STREAM_REQ(loop, req, read, data); |
||||
|
break; |
||||
|
|
||||
|
case UV_WRITE: |
||||
|
DELEGATE_STREAM_REQ(loop, (uv_write_t*) req, write, handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_ACCEPT: |
||||
|
DELEGATE_STREAM_REQ(loop, req, accept, data); |
||||
|
break; |
||||
|
|
||||
|
case UV_CONNECT: |
||||
|
DELEGATE_STREAM_REQ(loop, (uv_connect_t*) req, connect, handle); |
||||
|
break; |
||||
|
|
||||
|
case UV_SHUTDOWN: |
||||
|
/* Tcp shutdown requests don't come here. */ |
||||
|
assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE); |
||||
|
uv_process_pipe_shutdown_req( |
||||
|
loop, |
||||
|
(uv_pipe_t*) ((uv_shutdown_t*) req)->handle, |
||||
|
(uv_shutdown_t*) req); |
||||
|
break; |
||||
|
|
||||
|
case UV_UDP_RECV: |
||||
|
uv_process_udp_recv_req(loop, (uv_udp_t*) req->data, req); |
||||
|
break; |
||||
|
|
||||
|
case UV_UDP_SEND: |
||||
|
uv_process_udp_send_req(loop, |
||||
|
((uv_udp_send_t*) req)->handle, |
||||
|
(uv_udp_send_t*) req); |
||||
|
break; |
||||
|
|
||||
|
case UV_WAKEUP: |
||||
|
uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req); |
||||
|
break; |
||||
|
|
||||
|
case UV_POLL_REQ: |
||||
|
uv_process_poll_req(loop, (uv_poll_t*) req->data, req); |
||||
|
break; |
||||
|
|
||||
|
case UV_GETADDRINFO: |
||||
|
uv_process_getaddrinfo_req(loop, (uv_getaddrinfo_t*) req); |
||||
|
break; |
||||
|
|
||||
|
case UV_PROCESS_EXIT: |
||||
|
uv_process_proc_exit(loop, (uv_process_t*) req->data); |
||||
|
break; |
||||
|
|
||||
|
case UV_PROCESS_CLOSE: |
||||
|
uv_process_proc_close(loop, (uv_process_t*) req->data); |
||||
|
break; |
||||
|
|
||||
|
case UV_FS: |
||||
|
uv_process_fs_req(loop, (uv_fs_t*) req); |
||||
|
break; |
||||
|
|
||||
|
case UV_WORK: |
||||
|
uv_process_work_req(loop, (uv_work_t*) req); |
||||
|
break; |
||||
|
|
||||
|
case UV_FS_EVENT_REQ: |
||||
|
uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data); |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
assert(0); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#endif /* UV_WIN_REQ_INL_H_ */ |
@ -0,0 +1,67 @@ |
|||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to |
||||
|
* deal in the Software without restriction, including without limitation the |
||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
|
* sell copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
|
* IN THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#ifndef UV_WIN_STREAM_INL_H_ |
||||
|
#define UV_WIN_STREAM_INL_H_ |
||||
|
|
||||
|
#include <assert.h> |
||||
|
|
||||
|
#include "uv.h" |
||||
|
#include "internal.h" |
||||
|
#include "handle-inl.h" |
||||
|
#include "req-inl.h" |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_stream_init(uv_loop_t* loop, uv_stream_t* handle) { |
||||
|
uv_handle_init(loop, (uv_handle_t*) handle); |
||||
|
handle->write_queue_size = 0; |
||||
|
handle->activecnt = 0; |
||||
|
|
||||
|
loop->counters.stream_init++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
INLINE static void uv_connection_init(uv_stream_t* handle) { |
||||
|
handle->flags |= UV_HANDLE_CONNECTION; |
||||
|
handle->write_reqs_pending = 0; |
||||
|
|
||||
|
uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req)); |
||||
|
handle->read_req.event_handle = NULL; |
||||
|
handle->read_req.wait_handle = INVALID_HANDLE_VALUE; |
||||
|
handle->read_req.type = UV_READ; |
||||
|
handle->read_req.data = handle; |
||||
|
|
||||
|
handle->shutdown_req = NULL; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
INLINE static size_t uv_count_bufs(uv_buf_t bufs[], int count) { |
||||
|
size_t bytes = 0; |
||||
|
int i; |
||||
|
|
||||
|
for (i = 0; i < count; i++) { |
||||
|
bytes += (size_t)bufs[i].len; |
||||
|
} |
||||
|
|
||||
|
return bytes; |
||||
|
} |
||||
|
|
||||
|
#endif /* UV_WIN_STREAM_INL_H_ */ |
@ -0,0 +1,77 @@ |
|||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to |
||||
|
* deal in the Software without restriction, including without limitation the |
||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
|
* sell copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
|
* IN THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#include <errno.h> |
||||
|
|
||||
|
#ifndef _WIN32 |
||||
|
# include <fcntl.h> |
||||
|
# include <sys/socket.h> |
||||
|
# include <unistd.h> |
||||
|
#endif |
||||
|
|
||||
|
#include "uv.h" |
||||
|
#include "task.h" |
||||
|
|
||||
|
#define NUM_SOCKETS 64 |
||||
|
|
||||
|
|
||||
|
static int close_cb_called = 0; |
||||
|
|
||||
|
|
||||
|
static void poll_cb_fail(uv_poll_t* handle, int status, int events) { |
||||
|
ASSERT(0 && "poll_fail_cb should never be called"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void close_cb(uv_handle_t* handle) { |
||||
|
close_cb_called++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
TEST_IMPL(poll_close) { |
||||
|
uv_os_sock_t sockets[NUM_SOCKETS]; |
||||
|
uv_poll_t poll_handles[NUM_SOCKETS]; |
||||
|
int i; |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
{ |
||||
|
struct WSAData wsa_data; |
||||
|
int r = WSAStartup(MAKEWORD(2, 2), &wsa_data); |
||||
|
ASSERT(r == 0); |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
for (i = 0; i < NUM_SOCKETS; i++) { |
||||
|
sockets[i] = socket(AF_INET, SOCK_STREAM, 0); |
||||
|
uv_poll_init_socket(uv_default_loop(), &poll_handles[i], sockets[i]); |
||||
|
uv_poll_start(&poll_handles[i], UV_READABLE | UV_WRITABLE, NULL); |
||||
|
} |
||||
|
|
||||
|
for (i = 0; i < NUM_SOCKETS; i++) { |
||||
|
uv_close((uv_handle_t*) &poll_handles[i], close_cb); |
||||
|
} |
||||
|
|
||||
|
uv_run(uv_default_loop()); |
||||
|
|
||||
|
ASSERT(close_cb_called == NUM_SOCKETS); |
||||
|
|
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,111 @@ |
|||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to |
||||
|
* deal in the Software without restriction, including without limitation the |
||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
|
* sell copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
|
* IN THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#include "uv.h" |
||||
|
#include "task.h" |
||||
|
|
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
typedef struct { |
||||
|
uv_mutex_t mutex; |
||||
|
uv_sem_t sem; |
||||
|
int delay; |
||||
|
volatile int posted; |
||||
|
} worker_config; |
||||
|
|
||||
|
|
||||
|
static void worker(void* arg) { |
||||
|
worker_config* c = arg; |
||||
|
|
||||
|
if (c->delay) |
||||
|
uv_sleep(c->delay); |
||||
|
|
||||
|
uv_mutex_lock(&c->mutex); |
||||
|
ASSERT(c->posted == 0); |
||||
|
uv_sem_post(&c->sem); |
||||
|
c->posted = 1; |
||||
|
uv_mutex_unlock(&c->mutex); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
TEST_IMPL(semaphore_1) { |
||||
|
uv_thread_t thread; |
||||
|
worker_config wc; |
||||
|
|
||||
|
memset(&wc, 0, sizeof(wc)); |
||||
|
|
||||
|
ASSERT(0 == uv_sem_init(&wc.sem, 0)); |
||||
|
ASSERT(0 == uv_mutex_init(&wc.mutex)); |
||||
|
ASSERT(0 == uv_thread_create(&thread, worker, &wc)); |
||||
|
|
||||
|
uv_sleep(100); |
||||
|
uv_mutex_lock(&wc.mutex); |
||||
|
ASSERT(wc.posted == 1); |
||||
|
uv_sem_wait(&wc.sem); /* should not block */ |
||||
|
uv_mutex_unlock(&wc.mutex); /* ergo, it should be ok to unlock after wait */ |
||||
|
|
||||
|
ASSERT(0 == uv_thread_join(&thread)); |
||||
|
uv_mutex_destroy(&wc.mutex); |
||||
|
uv_sem_destroy(&wc.sem); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
TEST_IMPL(semaphore_2) { |
||||
|
uv_thread_t thread; |
||||
|
worker_config wc; |
||||
|
|
||||
|
memset(&wc, 0, sizeof(wc)); |
||||
|
wc.delay = 100; |
||||
|
|
||||
|
ASSERT(0 == uv_sem_init(&wc.sem, 0)); |
||||
|
ASSERT(0 == uv_mutex_init(&wc.mutex)); |
||||
|
ASSERT(0 == uv_thread_create(&thread, worker, &wc)); |
||||
|
|
||||
|
uv_sem_wait(&wc.sem); |
||||
|
|
||||
|
ASSERT(0 == uv_thread_join(&thread)); |
||||
|
uv_mutex_destroy(&wc.mutex); |
||||
|
uv_sem_destroy(&wc.sem); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
TEST_IMPL(semaphore_3) { |
||||
|
uv_sem_t sem; |
||||
|
|
||||
|
ASSERT(0 == uv_sem_init(&sem, 3)); |
||||
|
uv_sem_wait(&sem); /* should not block */ |
||||
|
uv_sem_wait(&sem); /* should not block */ |
||||
|
ASSERT(0 == uv_sem_trywait(&sem)); |
||||
|
ASSERT(-1 == uv_sem_trywait(&sem)); |
||||
|
|
||||
|
uv_sem_post(&sem); |
||||
|
ASSERT(0 == uv_sem_trywait(&sem)); |
||||
|
ASSERT(-1 == uv_sem_trywait(&sem)); |
||||
|
|
||||
|
uv_sem_destroy(&sem); |
||||
|
|
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,95 @@ |
|||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to |
||||
|
* deal in the Software without restriction, including without limitation the |
||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
|
* sell copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
|
* IN THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#include "uv.h" |
||||
|
#include "task.h" |
||||
|
|
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
|
||||
|
static int connect_cb_called; |
||||
|
static int write_cb_called; |
||||
|
static int close_cb_called; |
||||
|
|
||||
|
|
||||
|
static void close_cb(uv_handle_t* handle) { |
||||
|
close_cb_called++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void connect_cb(uv_connect_t* req, int status) { |
||||
|
ASSERT(status == -1); |
||||
|
connect_cb_called++; |
||||
|
uv_close((uv_handle_t*)req->handle, close_cb); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void write_cb(uv_write_t* req, int status) { |
||||
|
ASSERT(status == -1); |
||||
|
write_cb_called++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/*
|
||||
|
* Try to connect to an address on which nothing listens, get ECONNREFUSED |
||||
|
* (uv errno 12) and get connect_cb() called once with status != 0. |
||||
|
* Related issue: https://github.com/joyent/libuv/issues/443
|
||||
|
*/ |
||||
|
TEST_IMPL(tcp_connect_error_after_write) { |
||||
|
uv_connect_t connect_req; |
||||
|
struct sockaddr_in addr; |
||||
|
uv_write_t write_req; |
||||
|
uv_tcp_t conn; |
||||
|
uv_buf_t buf; |
||||
|
int r; |
||||
|
|
||||
|
#ifdef _WIN32 |
||||
|
fprintf(stderr, "This test is disabled on Windows for now.\n"); |
||||
|
fprintf(stderr, "See https://github.com/joyent/libuv/issues/444\n"); |
||||
|
return 0; /* windows slackers... */ |
||||
|
#endif |
||||
|
|
||||
|
addr = uv_ip4_addr("127.0.0.1", TEST_PORT); |
||||
|
buf = uv_buf_init("TEST", 4); |
||||
|
|
||||
|
r = uv_tcp_init(uv_default_loop(), &conn); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb); |
||||
|
ASSERT(r == -1); |
||||
|
ASSERT(uv_last_error(uv_default_loop()).code == UV_EBADF); |
||||
|
|
||||
|
r = uv_tcp_connect(&connect_req, &conn, addr, connect_cb); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_run(uv_default_loop()); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
ASSERT(connect_cb_called == 1); |
||||
|
ASSERT(write_cb_called == 1); |
||||
|
ASSERT(close_cb_called == 1); |
||||
|
|
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,129 @@ |
|||||
|
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
|
* |
||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
* of this software and associated documentation files (the "Software"), to |
||||
|
* deal in the Software without restriction, including without limitation the |
||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
||||
|
* sell copies of the Software, and to permit persons to whom the Software is |
||||
|
* furnished to do so, subject to the following conditions: |
||||
|
* |
||||
|
* The above copyright notice and this permission notice shall be included in |
||||
|
* all copies or substantial portions of the Software. |
||||
|
* |
||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
||||
|
* IN THE SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#include "uv.h" |
||||
|
#include "task.h" |
||||
|
|
||||
|
static void write_cb(uv_write_t* req, int status); |
||||
|
static void shutdown_cb(uv_shutdown_t* req, int status); |
||||
|
|
||||
|
static uv_tcp_t conn; |
||||
|
static uv_timer_t timer; |
||||
|
static uv_connect_t connect_req; |
||||
|
static uv_write_t write_req; |
||||
|
static uv_shutdown_t shutdown_req; |
||||
|
|
||||
|
static int connect_cb_called; |
||||
|
static int write_cb_called; |
||||
|
static int shutdown_cb_called; |
||||
|
|
||||
|
static int conn_close_cb_called; |
||||
|
static int timer_close_cb_called; |
||||
|
|
||||
|
|
||||
|
static void close_cb(uv_handle_t* handle) { |
||||
|
if (handle == (uv_handle_t*)&conn) |
||||
|
conn_close_cb_called++; |
||||
|
else if (handle == (uv_handle_t*)&timer) |
||||
|
timer_close_cb_called++; |
||||
|
else |
||||
|
ASSERT(0 && "bad handle in close_cb"); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) { |
||||
|
static char slab[64]; |
||||
|
return uv_buf_init(slab, sizeof(slab)); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void timer_cb(uv_timer_t* handle, int status) { |
||||
|
uv_buf_t buf; |
||||
|
int r; |
||||
|
|
||||
|
uv_close((uv_handle_t*)handle, close_cb); |
||||
|
|
||||
|
buf = uv_buf_init("TEST", 4); |
||||
|
r = uv_write(&write_req, (uv_stream_t*)&conn, &buf, 1, write_cb); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_shutdown(&shutdown_req, (uv_stream_t*)&conn, shutdown_cb); |
||||
|
ASSERT(r == 0); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void connect_cb(uv_connect_t* req, int status) { |
||||
|
ASSERT(status == 0); |
||||
|
connect_cb_called++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void read_cb(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void write_cb(uv_write_t* req, int status) { |
||||
|
ASSERT(status == 0); |
||||
|
write_cb_called++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static void shutdown_cb(uv_shutdown_t* req, int status) { |
||||
|
ASSERT(status == 0); |
||||
|
shutdown_cb_called++; |
||||
|
uv_close((uv_handle_t*)&conn, close_cb); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
TEST_IMPL(tcp_shutdown_after_write) { |
||||
|
struct sockaddr_in addr; |
||||
|
uv_loop_t* loop; |
||||
|
int r; |
||||
|
|
||||
|
addr = uv_ip4_addr("127.0.0.1", TEST_PORT); |
||||
|
loop = uv_default_loop(); |
||||
|
|
||||
|
r = uv_timer_init(loop, &timer); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_timer_start(&timer, timer_cb, 125, 0); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_tcp_init(loop, &conn); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_tcp_connect(&connect_req, &conn, addr, connect_cb); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_read_start((uv_stream_t*)&conn, alloc_cb, read_cb); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
r = uv_run(loop); |
||||
|
ASSERT(r == 0); |
||||
|
|
||||
|
ASSERT(connect_cb_called == 1); |
||||
|
ASSERT(write_cb_called == 1); |
||||
|
ASSERT(shutdown_cb_called == 1); |
||||
|
ASSERT(conn_close_cb_called == 1); |
||||
|
ASSERT(timer_close_cb_called == 1); |
||||
|
|
||||
|
return 0; |
||||
|
} |
Loading…
Reference in new issue