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