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