glx-multithread-texture: Avoid front-buffer rendering.
[piglit.git] / tests / util / piglit-subprocess.c
blob8cde2fee4d8c87891e4d4a7abb5a46a5bc5c97fa
1 /*
2 * Copyright © 2018 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include "piglit-subprocess.h"
26 #include <stdio.h>
28 #ifndef _WIN32
30 #include <unistd.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <poll.h>
36 #include <limits.h>
38 static bool
39 stream_data(pid_t pid,
40 int to_child,
41 int from_child,
42 size_t input_size,
43 const uint8_t *input,
44 size_t *output_size,
45 uint8_t **output)
47 bool ret = true;
48 size_t buf_size = 128;
50 *output = malloc(buf_size);
51 *output_size = 0;
53 while (true) {
54 int n_pollfds = 0;
55 struct pollfd pollfds[2];
57 if (to_child != -1) {
58 pollfds[n_pollfds].fd = to_child;
59 pollfds[n_pollfds].events = POLLOUT;
60 pollfds[n_pollfds].revents = 0;
61 n_pollfds++;
64 pollfds[n_pollfds].fd = from_child;
65 pollfds[n_pollfds].events = POLLIN;
66 pollfds[n_pollfds].revents = 0;
67 n_pollfds++;
69 int res = poll(pollfds, n_pollfds, INT_MAX);
71 if (res < 0) {
72 if (errno == EINTR)
73 continue;
74 fprintf(stderr, "poll: %s\n", strerror(errno));
75 ret = false;
76 goto done;
79 for (int i = 0; i < n_pollfds; i++) {
80 if (pollfds[i].revents &
81 ~(POLLIN | POLLOUT | POLLHUP)) {
82 ret = false;
83 goto done;
86 if (pollfds[i].fd == from_child &&
87 pollfds[i].revents) {
88 if (buf_size - *output_size < 128) {
89 buf_size *=2;
90 *output = realloc(*output, buf_size);
92 res = read(from_child,
93 *output + *output_size,
94 buf_size - *output_size);
95 if (res < 0) {
96 if (errno != EINTR) {
97 ret = false;
98 goto done;
100 } else if (res == 0) {
101 if (to_child != -1)
102 ret = false;
103 goto done;
104 } else {
105 *output_size += res;
107 } else if (pollfds[i].fd == to_child &&
108 pollfds[i].revents) {
109 res = write(to_child, input, input_size);
110 if (res < 0) {
111 ret = false;
112 goto done;
114 input += res;
115 input_size -= res;
117 if (input_size <= 0) {
118 close(to_child);
119 to_child = -1;
125 done:
126 if (to_child != -1)
127 close(to_child);
128 close(from_child);
130 if (!ret)
131 free(*output);
133 return ret;
136 bool
137 piglit_subprocess(char * const *arguments,
138 size_t input_size,
139 const uint8_t *input,
140 size_t *output_size,
141 uint8_t **output)
143 pid_t pid;
144 int stdin_pipe[2];
145 int stdout_pipe[2];
147 if (pipe(stdin_pipe) == -1) {
148 fprintf(stderr, "pipe: %s\n", strerror(errno));
149 return false;
151 if (pipe(stdout_pipe) == -1) {
152 fprintf(stderr, "pipe: %s\n", strerror(errno));
153 close(stdin_pipe[0]);
154 close(stdin_pipe[1]);
155 return false;
158 pid = fork();
160 if (pid < 0) {
161 fprintf(stderr, "fork failed: %s\n", strerror(errno));
162 return false;
163 } else if (pid == 0) {
164 dup2(stdin_pipe[0], STDIN_FILENO);
165 dup2(stdout_pipe[1], STDOUT_FILENO);
166 for (int i = 3; i < 256; i++)
167 close(i);
168 execvp(arguments[0], arguments);
169 fprintf(stderr, "%s: %s\n", arguments[0], strerror(errno));
170 _exit(EXIT_FAILURE);
171 } else {
172 close(stdin_pipe[0]);
173 close(stdout_pipe[1]);
175 bool ret = stream_data(pid,
176 stdin_pipe[1],
177 stdout_pipe[0],
178 input_size, input,
179 output_size, output);
181 int status;
182 while (waitpid(pid, &status, 0 /* options */) == -1);
184 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
185 if (ret)
186 free(*output);
187 return false;
190 return ret;
194 #else /* _WIN32 */
196 bool
197 piglit_subprocess(char * const *arguments,
198 size_t input_size,
199 const uint8_t *input,
200 size_t *output_size,
201 uint8_t **output)
203 fprintf(stderr, "piglit_subprocess is not implemented on Windows\n");
204 return false;
207 #endif /* _WIN32 */