1 | /* |
2 | * QEMU I/O channels external command driver |
3 | * |
4 | * Copyright (c) 2015 Red Hat, Inc. |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. |
18 | * |
19 | */ |
20 | |
21 | #include "qemu/osdep.h" |
22 | #include "io/channel-command.h" |
23 | #include "io/channel-watch.h" |
24 | #include "qapi/error.h" |
25 | #include "qemu/module.h" |
26 | #include "qemu/sockets.h" |
27 | #include "trace.h" |
28 | |
29 | |
30 | QIOChannelCommand * |
31 | qio_channel_command_new_pid(int writefd, |
32 | int readfd, |
33 | pid_t pid) |
34 | { |
35 | QIOChannelCommand *ioc; |
36 | |
37 | ioc = QIO_CHANNEL_COMMAND(object_new(TYPE_QIO_CHANNEL_COMMAND)); |
38 | |
39 | ioc->readfd = readfd; |
40 | ioc->writefd = writefd; |
41 | ioc->pid = pid; |
42 | |
43 | trace_qio_channel_command_new_pid(ioc, writefd, readfd, pid); |
44 | return ioc; |
45 | } |
46 | |
47 | |
48 | #ifndef WIN32 |
49 | QIOChannelCommand * |
50 | qio_channel_command_new_spawn(const char *const argv[], |
51 | int flags, |
52 | Error **errp) |
53 | { |
54 | pid_t pid = -1; |
55 | int stdinfd[2] = { -1, -1 }; |
56 | int stdoutfd[2] = { -1, -1 }; |
57 | int devnull = -1; |
58 | bool stdinnull = false, stdoutnull = false; |
59 | QIOChannelCommand *ioc; |
60 | |
61 | flags = flags & O_ACCMODE; |
62 | |
63 | if (flags == O_RDONLY) { |
64 | stdinnull = true; |
65 | } |
66 | if (flags == O_WRONLY) { |
67 | stdoutnull = true; |
68 | } |
69 | |
70 | if (stdinnull || stdoutnull) { |
71 | devnull = open("/dev/null" , O_RDWR); |
72 | if (devnull < 0) { |
73 | error_setg_errno(errp, errno, |
74 | "Unable to open /dev/null" ); |
75 | goto error; |
76 | } |
77 | } |
78 | |
79 | if ((!stdinnull && pipe(stdinfd) < 0) || |
80 | (!stdoutnull && pipe(stdoutfd) < 0)) { |
81 | error_setg_errno(errp, errno, |
82 | "Unable to open pipe" ); |
83 | goto error; |
84 | } |
85 | |
86 | pid = qemu_fork(errp); |
87 | if (pid < 0) { |
88 | goto error; |
89 | } |
90 | |
91 | if (pid == 0) { /* child */ |
92 | dup2(stdinnull ? devnull : stdinfd[0], STDIN_FILENO); |
93 | dup2(stdoutnull ? devnull : stdoutfd[1], STDOUT_FILENO); |
94 | /* Leave stderr connected to qemu's stderr */ |
95 | |
96 | if (!stdinnull) { |
97 | close(stdinfd[0]); |
98 | close(stdinfd[1]); |
99 | } |
100 | if (!stdoutnull) { |
101 | close(stdoutfd[0]); |
102 | close(stdoutfd[1]); |
103 | } |
104 | if (devnull != -1) { |
105 | close(devnull); |
106 | } |
107 | |
108 | execv(argv[0], (char * const *)argv); |
109 | _exit(1); |
110 | } |
111 | |
112 | if (!stdinnull) { |
113 | close(stdinfd[0]); |
114 | } |
115 | if (!stdoutnull) { |
116 | close(stdoutfd[1]); |
117 | } |
118 | |
119 | ioc = qio_channel_command_new_pid(stdinnull ? devnull : stdinfd[1], |
120 | stdoutnull ? devnull : stdoutfd[0], |
121 | pid); |
122 | trace_qio_channel_command_new_spawn(ioc, argv[0], flags); |
123 | return ioc; |
124 | |
125 | error: |
126 | if (devnull != -1) { |
127 | close(devnull); |
128 | } |
129 | if (stdinfd[0] != -1) { |
130 | close(stdinfd[0]); |
131 | } |
132 | if (stdinfd[1] != -1) { |
133 | close(stdinfd[1]); |
134 | } |
135 | if (stdoutfd[0] != -1) { |
136 | close(stdoutfd[0]); |
137 | } |
138 | if (stdoutfd[1] != -1) { |
139 | close(stdoutfd[1]); |
140 | } |
141 | return NULL; |
142 | } |
143 | |
144 | #else /* WIN32 */ |
145 | QIOChannelCommand * |
146 | qio_channel_command_new_spawn(const char *const argv[], |
147 | int flags, |
148 | Error **errp) |
149 | { |
150 | error_setg_errno(errp, ENOSYS, |
151 | "Command spawn not supported on this platform" ); |
152 | return NULL; |
153 | } |
154 | #endif /* WIN32 */ |
155 | |
156 | #ifndef WIN32 |
157 | static int qio_channel_command_abort(QIOChannelCommand *ioc, |
158 | Error **errp) |
159 | { |
160 | pid_t ret; |
161 | int status; |
162 | int step = 0; |
163 | |
164 | /* See if intermediate process has exited; if not, try a nice |
165 | * SIGTERM followed by a more severe SIGKILL. |
166 | */ |
167 | rewait: |
168 | trace_qio_channel_command_abort(ioc, ioc->pid); |
169 | ret = waitpid(ioc->pid, &status, WNOHANG); |
170 | trace_qio_channel_command_wait(ioc, ioc->pid, ret, status); |
171 | if (ret == (pid_t)-1) { |
172 | if (errno == EINTR) { |
173 | goto rewait; |
174 | } else { |
175 | error_setg_errno(errp, errno, |
176 | "Cannot wait on pid %llu" , |
177 | (unsigned long long)ioc->pid); |
178 | return -1; |
179 | } |
180 | } else if (ret == 0) { |
181 | if (step == 0) { |
182 | kill(ioc->pid, SIGTERM); |
183 | } else if (step == 1) { |
184 | kill(ioc->pid, SIGKILL); |
185 | } else { |
186 | error_setg(errp, |
187 | "Process %llu refused to die" , |
188 | (unsigned long long)ioc->pid); |
189 | return -1; |
190 | } |
191 | step++; |
192 | usleep(10 * 1000); |
193 | goto rewait; |
194 | } |
195 | |
196 | return 0; |
197 | } |
198 | #endif /* ! WIN32 */ |
199 | |
200 | |
201 | static void qio_channel_command_init(Object *obj) |
202 | { |
203 | QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj); |
204 | ioc->readfd = -1; |
205 | ioc->writefd = -1; |
206 | ioc->pid = -1; |
207 | } |
208 | |
209 | static void qio_channel_command_finalize(Object *obj) |
210 | { |
211 | QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj); |
212 | if (ioc->readfd != -1) { |
213 | close(ioc->readfd); |
214 | } |
215 | if (ioc->writefd != -1 && |
216 | ioc->writefd != ioc->readfd) { |
217 | close(ioc->writefd); |
218 | } |
219 | ioc->writefd = ioc->readfd = -1; |
220 | if (ioc->pid > 0) { |
221 | #ifndef WIN32 |
222 | qio_channel_command_abort(ioc, NULL); |
223 | #endif |
224 | } |
225 | } |
226 | |
227 | |
228 | static ssize_t qio_channel_command_readv(QIOChannel *ioc, |
229 | const struct iovec *iov, |
230 | size_t niov, |
231 | int **fds, |
232 | size_t *nfds, |
233 | Error **errp) |
234 | { |
235 | QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); |
236 | ssize_t ret; |
237 | |
238 | retry: |
239 | ret = readv(cioc->readfd, iov, niov); |
240 | if (ret < 0) { |
241 | if (errno == EAGAIN) { |
242 | return QIO_CHANNEL_ERR_BLOCK; |
243 | } |
244 | if (errno == EINTR) { |
245 | goto retry; |
246 | } |
247 | |
248 | error_setg_errno(errp, errno, |
249 | "Unable to read from command" ); |
250 | return -1; |
251 | } |
252 | |
253 | return ret; |
254 | } |
255 | |
256 | static ssize_t qio_channel_command_writev(QIOChannel *ioc, |
257 | const struct iovec *iov, |
258 | size_t niov, |
259 | int *fds, |
260 | size_t nfds, |
261 | Error **errp) |
262 | { |
263 | QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); |
264 | ssize_t ret; |
265 | |
266 | retry: |
267 | ret = writev(cioc->writefd, iov, niov); |
268 | if (ret <= 0) { |
269 | if (errno == EAGAIN) { |
270 | return QIO_CHANNEL_ERR_BLOCK; |
271 | } |
272 | if (errno == EINTR) { |
273 | goto retry; |
274 | } |
275 | error_setg_errno(errp, errno, "%s" , |
276 | "Unable to write to command" ); |
277 | return -1; |
278 | } |
279 | return ret; |
280 | } |
281 | |
282 | static int qio_channel_command_set_blocking(QIOChannel *ioc, |
283 | bool enabled, |
284 | Error **errp) |
285 | { |
286 | QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); |
287 | |
288 | if (enabled) { |
289 | qemu_set_block(cioc->writefd); |
290 | qemu_set_block(cioc->readfd); |
291 | } else { |
292 | qemu_set_nonblock(cioc->writefd); |
293 | qemu_set_nonblock(cioc->readfd); |
294 | } |
295 | |
296 | return 0; |
297 | } |
298 | |
299 | |
300 | static int qio_channel_command_close(QIOChannel *ioc, |
301 | Error **errp) |
302 | { |
303 | QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); |
304 | int rv = 0; |
305 | #ifndef WIN32 |
306 | pid_t wp; |
307 | #endif |
308 | |
309 | /* We close FDs before killing, because that |
310 | * gives a better chance of clean shutdown |
311 | */ |
312 | if (cioc->readfd != -1 && |
313 | close(cioc->readfd) < 0) { |
314 | rv = -1; |
315 | } |
316 | if (cioc->writefd != -1 && |
317 | cioc->writefd != cioc->readfd && |
318 | close(cioc->writefd) < 0) { |
319 | rv = -1; |
320 | } |
321 | cioc->writefd = cioc->readfd = -1; |
322 | |
323 | #ifndef WIN32 |
324 | do { |
325 | wp = waitpid(cioc->pid, NULL, 0); |
326 | } while (wp == (pid_t)-1 && errno == EINTR); |
327 | if (wp == (pid_t)-1) { |
328 | error_setg_errno(errp, errno, "Failed to wait for pid %llu" , |
329 | (unsigned long long)cioc->pid); |
330 | return -1; |
331 | } |
332 | #endif |
333 | |
334 | if (rv < 0) { |
335 | error_setg_errno(errp, errno, "%s" , |
336 | "Unable to close command" ); |
337 | } |
338 | return rv; |
339 | } |
340 | |
341 | |
342 | static void qio_channel_command_set_aio_fd_handler(QIOChannel *ioc, |
343 | AioContext *ctx, |
344 | IOHandler *io_read, |
345 | IOHandler *io_write, |
346 | void *opaque) |
347 | { |
348 | QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); |
349 | aio_set_fd_handler(ctx, cioc->readfd, false, io_read, NULL, NULL, opaque); |
350 | aio_set_fd_handler(ctx, cioc->writefd, false, NULL, io_write, NULL, opaque); |
351 | } |
352 | |
353 | |
354 | static GSource *qio_channel_command_create_watch(QIOChannel *ioc, |
355 | GIOCondition condition) |
356 | { |
357 | QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc); |
358 | return qio_channel_create_fd_pair_watch(ioc, |
359 | cioc->readfd, |
360 | cioc->writefd, |
361 | condition); |
362 | } |
363 | |
364 | |
365 | static void qio_channel_command_class_init(ObjectClass *klass, |
366 | void *class_data G_GNUC_UNUSED) |
367 | { |
368 | QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); |
369 | |
370 | ioc_klass->io_writev = qio_channel_command_writev; |
371 | ioc_klass->io_readv = qio_channel_command_readv; |
372 | ioc_klass->io_set_blocking = qio_channel_command_set_blocking; |
373 | ioc_klass->io_close = qio_channel_command_close; |
374 | ioc_klass->io_create_watch = qio_channel_command_create_watch; |
375 | ioc_klass->io_set_aio_fd_handler = qio_channel_command_set_aio_fd_handler; |
376 | } |
377 | |
378 | static const TypeInfo qio_channel_command_info = { |
379 | .parent = TYPE_QIO_CHANNEL, |
380 | .name = TYPE_QIO_CHANNEL_COMMAND, |
381 | .instance_size = sizeof(QIOChannelCommand), |
382 | .instance_init = qio_channel_command_init, |
383 | .instance_finalize = qio_channel_command_finalize, |
384 | .class_init = qio_channel_command_class_init, |
385 | }; |
386 | |
387 | static void qio_channel_command_register_types(void) |
388 | { |
389 | type_register_static(&qio_channel_command_info); |
390 | } |
391 | |
392 | type_init(qio_channel_command_register_types); |
393 | |