1 | /* Copyright (c) 2015, Ben Noordhuis <info@bnoordhuis.nl> |
2 | * |
3 | * Permission to use, copy, modify, and/or distribute this software for any |
4 | * purpose with or without fee is hereby granted, provided that the above |
5 | * copyright notice and this permission notice appear in all copies. |
6 | * |
7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
10 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
12 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
13 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
14 | */ |
15 | |
16 | #include "uv.h" |
17 | #include "task.h" |
18 | |
19 | #ifdef _WIN32 |
20 | |
21 | TEST_IMPL(pipe_set_non_blocking) { |
22 | RETURN_SKIP("Test not implemented on Windows." ); |
23 | } |
24 | |
25 | #else /* !_WIN32 */ |
26 | |
27 | #include <errno.h> |
28 | #include <string.h> |
29 | #include <sys/socket.h> |
30 | #include <sys/types.h> |
31 | #include <sys/un.h> |
32 | #include <unistd.h> |
33 | |
34 | struct thread_ctx { |
35 | uv_barrier_t barrier; |
36 | int fd; |
37 | }; |
38 | |
39 | static void thread_main(void* arg) { |
40 | struct thread_ctx* ctx; |
41 | char buf[4096]; |
42 | ssize_t n; |
43 | |
44 | ctx = arg; |
45 | uv_barrier_wait(&ctx->barrier); |
46 | |
47 | do |
48 | n = read(ctx->fd, buf, sizeof(buf)); |
49 | while (n > 0 || (n == -1 && errno == EINTR)); |
50 | |
51 | ASSERT(n == 0); |
52 | } |
53 | |
54 | TEST_IMPL(pipe_set_non_blocking) { |
55 | struct thread_ctx ctx; |
56 | uv_pipe_t pipe_handle; |
57 | uv_thread_t thread; |
58 | size_t nwritten; |
59 | char data[4096]; |
60 | uv_buf_t buf; |
61 | int fd[2]; |
62 | int n; |
63 | |
64 | ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0)); |
65 | ASSERT(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, fd)); |
66 | ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0])); |
67 | ASSERT(0 == uv_stream_set_blocking((uv_stream_t*) &pipe_handle, 1)); |
68 | |
69 | ctx.fd = fd[1]; |
70 | ASSERT(0 == uv_barrier_init(&ctx.barrier, 2)); |
71 | ASSERT(0 == uv_thread_create(&thread, thread_main, &ctx)); |
72 | uv_barrier_wait(&ctx.barrier); |
73 | |
74 | buf.len = sizeof(data); |
75 | buf.base = data; |
76 | memset(data, '.', sizeof(data)); |
77 | |
78 | nwritten = 0; |
79 | while (nwritten < 10 << 20) { |
80 | /* The stream is in blocking mode so uv_try_write() should always succeed |
81 | * with the exact number of bytes that we wanted written. |
82 | */ |
83 | n = uv_try_write((uv_stream_t*) &pipe_handle, &buf, 1); |
84 | ASSERT(n == sizeof(data)); |
85 | nwritten += n; |
86 | } |
87 | |
88 | uv_close((uv_handle_t*) &pipe_handle, NULL); |
89 | ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); |
90 | |
91 | ASSERT(0 == uv_thread_join(&thread)); |
92 | ASSERT(0 == close(fd[1])); /* fd[0] is closed by uv_close(). */ |
93 | uv_barrier_destroy(&ctx.barrier); |
94 | |
95 | MAKE_VALGRIND_HAPPY(); |
96 | return 0; |
97 | } |
98 | |
99 | #endif /* !_WIN32 */ |
100 | |