1/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21
22#ifndef _WIN32
23
24#include <stdlib.h>
25#include <unistd.h>
26#include <sys/wait.h>
27#include <sys/types.h>
28
29#include "uv.h"
30#include "task.h"
31
32void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t* buf)
33{
34 static char buffer[1024];
35
36 buf->base = buffer;
37 buf->len = sizeof(buffer);
38}
39
40void read_stdin(uv_stream_t *stream, ssize_t nread, const uv_buf_t* buf)
41{
42 if (nread < 0) {
43 uv_close((uv_handle_t*)stream, NULL);
44 return;
45 }
46}
47
48/*
49 * This test is a reproduction of joyent/libuv#1419 .
50 */
51TEST_IMPL(pipe_close_stdout_read_stdin) {
52 int r = -1;
53 int pid;
54 int fd[2];
55 int status;
56 char buf;
57 uv_pipe_t stdin_pipe;
58
59 r = pipe(fd);
60 ASSERT(r == 0);
61
62 if ((pid = fork()) == 0) {
63 /*
64 * Make the read side of the pipe our stdin.
65 * The write side will be closed by the parent process.
66 */
67 close(fd[1]);
68 /* block until write end of pipe is closed */
69 r = read(fd[0], &buf, 1);
70 ASSERT(-1 <= r && r <= 1);
71 close(0);
72 r = dup(fd[0]);
73 ASSERT(r != -1);
74
75 /* Create a stream that reads from the pipe. */
76 r = uv_pipe_init(uv_default_loop(), (uv_pipe_t *)&stdin_pipe, 0);
77 ASSERT(r == 0);
78
79 r = uv_pipe_open((uv_pipe_t *)&stdin_pipe, 0);
80 ASSERT(r == 0);
81
82 r = uv_read_start((uv_stream_t *)&stdin_pipe, alloc_buffer, read_stdin);
83 ASSERT(r == 0);
84
85 /*
86 * Because the other end of the pipe was closed, there should
87 * be no event left to process after one run of the event loop.
88 * Otherwise, it means that events were not processed correctly.
89 */
90 ASSERT(uv_run(uv_default_loop(), UV_RUN_NOWAIT) == 0);
91 } else {
92 /*
93 * Close both ends of the pipe so that the child
94 * get a POLLHUP event when it tries to read from
95 * the other end.
96 */
97 close(fd[1]);
98 close(fd[0]);
99
100 waitpid(pid, &status, 0);
101 ASSERT(WIFEXITED(status) && WEXITSTATUS(status) == 0);
102 }
103
104 MAKE_VALGRIND_HAPPY();
105 return 0;
106}
107
108#else
109
110typedef int file_has_no_tests; /* ISO C forbids an empty translation unit. */
111
112#endif /* ifndef _WIN32 */
113