]> git.proxmox.com Git - mirror_qemu.git/blame - io/channel-command.c
io: replace qemu_set{_non}block()
[mirror_qemu.git] / io / channel-command.c
CommitLineData
195e14d0
DB
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
c8198bd5 9 * version 2.1 of the License, or (at your option) any later version.
195e14d0
DB
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
cae9fc56 21#include "qemu/osdep.h"
195e14d0
DB
22#include "io/channel-command.h"
23#include "io/channel-watch.h"
da34e65c 24#include "qapi/error.h"
0b8fa32f 25#include "qemu/module.h"
195e14d0
DB
26#include "qemu/sockets.h"
27#include "trace.h"
28
05e50e8f
MAL
29#ifndef WIN32
30/**
31 * qio_channel_command_new_pid:
32 * @writefd: the FD connected to the command's stdin
33 * @readfd: the FD connected to the command's stdout
34 * @pid: the PID of the running child command
35 * @errp: pointer to a NULL-initialized error object
36 *
37 * Create a channel for performing I/O with the
38 * previously spawned command identified by @pid.
39 * The two file descriptors provide the connection
40 * to command's stdio streams, either one or which
41 * may be -1 to indicate that stream is not open.
42 *
43 * The channel will take ownership of the process
44 * @pid and will kill it when closing the channel.
45 * Similarly it will take responsibility for
46 * closing the file descriptors @writefd and @readfd.
47 *
48 * Returns: the command channel object, or NULL on error
49 */
50static QIOChannelCommand *
195e14d0
DB
51qio_channel_command_new_pid(int writefd,
52 int readfd,
53 pid_t pid)
54{
55 QIOChannelCommand *ioc;
56
57 ioc = QIO_CHANNEL_COMMAND(object_new(TYPE_QIO_CHANNEL_COMMAND));
58
59 ioc->readfd = readfd;
60 ioc->writefd = writefd;
61 ioc->pid = pid;
62
63 trace_qio_channel_command_new_pid(ioc, writefd, readfd, pid);
64 return ioc;
65}
66
195e14d0
DB
67QIOChannelCommand *
68qio_channel_command_new_spawn(const char *const argv[],
69 int flags,
70 Error **errp)
71{
72 pid_t pid = -1;
73 int stdinfd[2] = { -1, -1 };
74 int stdoutfd[2] = { -1, -1 };
75 int devnull = -1;
76 bool stdinnull = false, stdoutnull = false;
77 QIOChannelCommand *ioc;
78
79 flags = flags & O_ACCMODE;
80
81 if (flags == O_RDONLY) {
82 stdinnull = true;
83 }
84 if (flags == O_WRONLY) {
85 stdoutnull = true;
86 }
87
88 if (stdinnull || stdoutnull) {
89 devnull = open("/dev/null", O_RDWR);
e155494c 90 if (devnull < 0) {
195e14d0
DB
91 error_setg_errno(errp, errno,
92 "Unable to open /dev/null");
93 goto error;
94 }
95 }
96
d640b59e
MAL
97 if ((!stdinnull && !g_unix_open_pipe(stdinfd, FD_CLOEXEC, NULL)) ||
98 (!stdoutnull && !g_unix_open_pipe(stdoutfd, FD_CLOEXEC, NULL))) {
195e14d0
DB
99 error_setg_errno(errp, errno,
100 "Unable to open pipe");
101 goto error;
102 }
103
104 pid = qemu_fork(errp);
105 if (pid < 0) {
106 goto error;
107 }
108
109 if (pid == 0) { /* child */
110 dup2(stdinnull ? devnull : stdinfd[0], STDIN_FILENO);
111 dup2(stdoutnull ? devnull : stdoutfd[1], STDOUT_FILENO);
112 /* Leave stderr connected to qemu's stderr */
113
114 if (!stdinnull) {
115 close(stdinfd[0]);
116 close(stdinfd[1]);
117 }
118 if (!stdoutnull) {
119 close(stdoutfd[0]);
120 close(stdoutfd[1]);
121 }
e155494c
DB
122 if (devnull != -1) {
123 close(devnull);
124 }
195e14d0
DB
125
126 execv(argv[0], (char * const *)argv);
127 _exit(1);
128 }
129
130 if (!stdinnull) {
131 close(stdinfd[0]);
132 }
133 if (!stdoutnull) {
134 close(stdoutfd[1]);
135 }
136
137 ioc = qio_channel_command_new_pid(stdinnull ? devnull : stdinfd[1],
138 stdoutnull ? devnull : stdoutfd[0],
139 pid);
140 trace_qio_channel_command_new_spawn(ioc, argv[0], flags);
141 return ioc;
142
143 error:
e155494c
DB
144 if (devnull != -1) {
145 close(devnull);
146 }
195e14d0
DB
147 if (stdinfd[0] != -1) {
148 close(stdinfd[0]);
149 }
150 if (stdinfd[1] != -1) {
151 close(stdinfd[1]);
152 }
153 if (stdoutfd[0] != -1) {
154 close(stdoutfd[0]);
155 }
156 if (stdoutfd[1] != -1) {
157 close(stdoutfd[1]);
158 }
159 return NULL;
160}
161
162#else /* WIN32 */
163QIOChannelCommand *
164qio_channel_command_new_spawn(const char *const argv[],
165 int flags,
166 Error **errp)
167{
168 error_setg_errno(errp, ENOSYS,
169 "Command spawn not supported on this platform");
170 return NULL;
171}
172#endif /* WIN32 */
173
174#ifndef WIN32
175static int qio_channel_command_abort(QIOChannelCommand *ioc,
176 Error **errp)
177{
178 pid_t ret;
179 int status;
180 int step = 0;
181
182 /* See if intermediate process has exited; if not, try a nice
183 * SIGTERM followed by a more severe SIGKILL.
184 */
185 rewait:
186 trace_qio_channel_command_abort(ioc, ioc->pid);
187 ret = waitpid(ioc->pid, &status, WNOHANG);
188 trace_qio_channel_command_wait(ioc, ioc->pid, ret, status);
189 if (ret == (pid_t)-1) {
190 if (errno == EINTR) {
191 goto rewait;
192 } else {
193 error_setg_errno(errp, errno,
194 "Cannot wait on pid %llu",
195 (unsigned long long)ioc->pid);
196 return -1;
197 }
198 } else if (ret == 0) {
199 if (step == 0) {
200 kill(ioc->pid, SIGTERM);
201 } else if (step == 1) {
202 kill(ioc->pid, SIGKILL);
203 } else {
204 error_setg(errp,
205 "Process %llu refused to die",
206 (unsigned long long)ioc->pid);
207 return -1;
208 }
0c0a55b2 209 step++;
195e14d0
DB
210 usleep(10 * 1000);
211 goto rewait;
212 }
213
214 return 0;
215}
216#endif /* ! WIN32 */
217
218
219static void qio_channel_command_init(Object *obj)
220{
221 QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj);
222 ioc->readfd = -1;
223 ioc->writefd = -1;
224 ioc->pid = -1;
225}
226
227static void qio_channel_command_finalize(Object *obj)
228{
229 QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj);
230 if (ioc->readfd != -1) {
231 close(ioc->readfd);
195e14d0 232 }
e155494c
DB
233 if (ioc->writefd != -1 &&
234 ioc->writefd != ioc->readfd) {
195e14d0 235 close(ioc->writefd);
195e14d0 236 }
e155494c 237 ioc->writefd = ioc->readfd = -1;
195e14d0
DB
238 if (ioc->pid > 0) {
239#ifndef WIN32
240 qio_channel_command_abort(ioc, NULL);
241#endif
242 }
243}
244
245
246static ssize_t qio_channel_command_readv(QIOChannel *ioc,
247 const struct iovec *iov,
248 size_t niov,
249 int **fds,
250 size_t *nfds,
251 Error **errp)
252{
253 QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
254 ssize_t ret;
255
256 retry:
257 ret = readv(cioc->readfd, iov, niov);
258 if (ret < 0) {
30fd3e27 259 if (errno == EAGAIN) {
195e14d0
DB
260 return QIO_CHANNEL_ERR_BLOCK;
261 }
262 if (errno == EINTR) {
263 goto retry;
264 }
265
266 error_setg_errno(errp, errno,
267 "Unable to read from command");
268 return -1;
269 }
270
271 return ret;
272}
273
274static ssize_t qio_channel_command_writev(QIOChannel *ioc,
275 const struct iovec *iov,
276 size_t niov,
277 int *fds,
278 size_t nfds,
279 Error **errp)
280{
281 QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
282 ssize_t ret;
283
284 retry:
285 ret = writev(cioc->writefd, iov, niov);
286 if (ret <= 0) {
30fd3e27 287 if (errno == EAGAIN) {
195e14d0
DB
288 return QIO_CHANNEL_ERR_BLOCK;
289 }
290 if (errno == EINTR) {
291 goto retry;
292 }
293 error_setg_errno(errp, errno, "%s",
294 "Unable to write to command");
295 return -1;
296 }
297 return ret;
298}
299
300static int qio_channel_command_set_blocking(QIOChannel *ioc,
301 bool enabled,
302 Error **errp)
303{
17fc1245
MAL
304#ifdef WIN32
305 /* command spawn is not supported on win32 */
306 g_assert_not_reached();
307#else
195e14d0
DB
308 QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
309
17fc1245
MAL
310 if (!g_unix_set_fd_nonblocking(cioc->writefd, !enabled, NULL) ||
311 !g_unix_set_fd_nonblocking(cioc->readfd, !enabled, NULL)) {
312 error_setg_errno(errp, errno, "Failed to set FD nonblocking");
313 return -1;
195e14d0 314 }
17fc1245 315#endif
195e14d0
DB
316 return 0;
317}
318
319
320static int qio_channel_command_close(QIOChannel *ioc,
321 Error **errp)
322{
323 QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
324 int rv = 0;
fe823b6f
TH
325#ifndef WIN32
326 pid_t wp;
327#endif
195e14d0
DB
328
329 /* We close FDs before killing, because that
330 * gives a better chance of clean shutdown
331 */
e155494c
DB
332 if (cioc->readfd != -1 &&
333 close(cioc->readfd) < 0) {
195e14d0
DB
334 rv = -1;
335 }
e155494c
DB
336 if (cioc->writefd != -1 &&
337 cioc->writefd != cioc->readfd &&
338 close(cioc->writefd) < 0) {
195e14d0
DB
339 rv = -1;
340 }
e155494c 341 cioc->writefd = cioc->readfd = -1;
fe823b6f 342
195e14d0 343#ifndef WIN32
fe823b6f
TH
344 do {
345 wp = waitpid(cioc->pid, NULL, 0);
346 } while (wp == (pid_t)-1 && errno == EINTR);
347 if (wp == (pid_t)-1) {
348 error_setg_errno(errp, errno, "Failed to wait for pid %llu",
349 (unsigned long long)cioc->pid);
195e14d0
DB
350 return -1;
351 }
352#endif
fe823b6f 353
195e14d0
DB
354 if (rv < 0) {
355 error_setg_errno(errp, errno, "%s",
356 "Unable to close command");
357 }
358 return rv;
359}
360
361
bf88c124
PB
362static void qio_channel_command_set_aio_fd_handler(QIOChannel *ioc,
363 AioContext *ctx,
364 IOHandler *io_read,
365 IOHandler *io_write,
366 void *opaque)
367{
368 QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
826cc324
SH
369 aio_set_fd_handler(ctx, cioc->readfd, false,
370 io_read, NULL, NULL, NULL, opaque);
371 aio_set_fd_handler(ctx, cioc->writefd, false,
372 NULL, io_write, NULL, NULL, opaque);
bf88c124
PB
373}
374
375
195e14d0
DB
376static GSource *qio_channel_command_create_watch(QIOChannel *ioc,
377 GIOCondition condition)
378{
379 QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
380 return qio_channel_create_fd_pair_watch(ioc,
381 cioc->readfd,
382 cioc->writefd,
383 condition);
384}
385
386
387static void qio_channel_command_class_init(ObjectClass *klass,
388 void *class_data G_GNUC_UNUSED)
389{
390 QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
391
392 ioc_klass->io_writev = qio_channel_command_writev;
393 ioc_klass->io_readv = qio_channel_command_readv;
394 ioc_klass->io_set_blocking = qio_channel_command_set_blocking;
395 ioc_klass->io_close = qio_channel_command_close;
396 ioc_klass->io_create_watch = qio_channel_command_create_watch;
bf88c124 397 ioc_klass->io_set_aio_fd_handler = qio_channel_command_set_aio_fd_handler;
195e14d0
DB
398}
399
400static const TypeInfo qio_channel_command_info = {
401 .parent = TYPE_QIO_CHANNEL,
402 .name = TYPE_QIO_CHANNEL_COMMAND,
403 .instance_size = sizeof(QIOChannelCommand),
404 .instance_init = qio_channel_command_init,
405 .instance_finalize = qio_channel_command_finalize,
406 .class_init = qio_channel_command_class_init,
407};
408
409static void qio_channel_command_register_types(void)
410{
411 type_register_static(&qio_channel_command_info);
412}
413
414type_init(qio_channel_command_register_types);