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