diff --git a/include/io/channel-command.h b/include/io/channel-command.h index bd3c59946f..cfc177e786 100644 --- a/include/io/channel-command.h +++ b/include/io/channel-command.h @@ -51,7 +51,7 @@ struct QIOChannelCommand { * @writefd: the FD connected to the command's stdin * @readfd: the FD connected to the command's stdout * @pid: the PID of the running child command - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Create a channel for performing I/O with the * previously spawned command identified by @pid. @@ -75,7 +75,7 @@ qio_channel_command_new_pid(int writefd, * qio_channel_command_new_spawn: * @argv: the NULL terminated list of command arguments * @flags: the I/O mode, one of O_RDONLY, O_WRONLY, O_RDWR - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Create a channel for performing I/O with the * command to be spawned with arguments @argv. diff --git a/include/io/channel-socket.h b/include/io/channel-socket.h index 0719757b0f..810537ef6f 100644 --- a/include/io/channel-socket.h +++ b/include/io/channel-socket.h @@ -67,7 +67,7 @@ qio_channel_socket_new(void); /** * qio_channel_socket_new_fd: * @fd: the socket file descriptor - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Create a channel for performing I/O on the socket * connection represented by the file descriptor @fd. @@ -83,7 +83,7 @@ qio_channel_socket_new_fd(int fd, * qio_channel_socket_connect_sync: * @ioc: the socket channel object * @addr: the address to connect to - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Attempt to connect to the address @addr. This method * will run in the foreground so the caller will not regain @@ -118,7 +118,7 @@ void qio_channel_socket_connect_async(QIOChannelSocket *ioc, * qio_channel_socket_listen_sync: * @ioc: the socket channel object * @addr: the address to listen to - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Attempt to listen to the address @addr. This method * will run in the foreground so the caller will not regain @@ -154,7 +154,7 @@ void qio_channel_socket_listen_async(QIOChannelSocket *ioc, * @ioc: the socket channel object * @localAddr: the address to local bind address * @remoteAddr: the address to remote peer address - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Attempt to initialize a datagram socket bound to * @localAddr and communicating with peer @remoteAddr. @@ -193,7 +193,7 @@ void qio_channel_socket_dgram_async(QIOChannelSocket *ioc, /** * qio_channel_socket_get_local_address: * @ioc: the socket channel object - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Get the string representation of the local socket * address. A pointer to the allocated address information @@ -210,7 +210,7 @@ qio_channel_socket_get_local_address(QIOChannelSocket *ioc, /** * qio_channel_socket_get_remote_address: * @ioc: the socket channel object - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Get the string representation of the local socket * address. A pointer to the allocated address information @@ -228,7 +228,7 @@ qio_channel_socket_get_remote_address(QIOChannelSocket *ioc, /** * qio_channel_socket_accept: * @ioc: the socket channel object - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * If the socket represents a server, then this accepts * a new client connection. The returned channel will diff --git a/include/io/channel-tls.h b/include/io/channel-tls.h index 0298b1770e..322eccbaae 100644 --- a/include/io/channel-tls.h +++ b/include/io/channel-tls.h @@ -55,7 +55,7 @@ struct QIOChannelTLS { * @master: the underlying channel object * @creds: the credentials to use for TLS handshake * @aclname: the access control list for validating clients - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Create a new TLS channel that runs the server side of * a TLS session. The TLS session handshake will use the @@ -85,7 +85,7 @@ qio_channel_tls_new_server(QIOChannel *master, * @master: the underlying channel object * @creds: the credentials to use for TLS handshake * @hostname: the user specified server hostname - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Create a new TLS channel that runs the client side of * a TLS session. The TLS session handshake will use the diff --git a/include/io/channel.h b/include/io/channel.h index 4ecec98bf4..3e17fe7129 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -152,7 +152,7 @@ bool qio_channel_has_feature(QIOChannel *ioc, * @niov: the length of the @iov array * @fds: pointer to an array that will received file handles * @nfds: pointer filled with number of elements in @fds on return - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Read data from the IO channel, storing it in the * memory regions referenced by @iov. Each element @@ -198,7 +198,7 @@ ssize_t qio_channel_readv_full(QIOChannel *ioc, * @niov: the length of the @iov array * @fds: an array of file handles to send * @nfds: number of file handles in @fds - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Write data to the IO channel, reading it from the * memory regions referenced by @iov. Each element @@ -237,7 +237,7 @@ ssize_t qio_channel_writev_full(QIOChannel *ioc, * @ioc: the channel object * @iov: the array of memory regions to read data into * @niov: the length of the @iov array - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Behaves as qio_channel_readv_full() but does not support * receiving of file handles. @@ -252,7 +252,7 @@ ssize_t qio_channel_readv(QIOChannel *ioc, * @ioc: the channel object * @iov: the array of memory regions to write data from * @niov: the length of the @iov array - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Behaves as qio_channel_writev_full() but does not support * sending of file handles. @@ -267,7 +267,7 @@ ssize_t qio_channel_writev(QIOChannel *ioc, * @ioc: the channel object * @buf: the memory region to read data into * @buflen: the length of @buf - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Behaves as qio_channel_readv_full() but does not support * receiving of file handles, and only supports reading into @@ -283,7 +283,7 @@ ssize_t qio_channel_read(QIOChannel *ioc, * @ioc: the channel object * @buf: the memory regions to send data from * @buflen: the length of @buf - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Behaves as qio_channel_writev_full() but does not support * sending of file handles, and only supports writing from a @@ -298,7 +298,7 @@ ssize_t qio_channel_write(QIOChannel *ioc, * qio_channel_set_blocking: * @ioc: the channel object * @enabled: the blocking flag state - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * If @enabled is true, then the channel is put into * blocking mode, otherwise it will be non-blocking. @@ -314,7 +314,7 @@ int qio_channel_set_blocking(QIOChannel *ioc, /** * qio_channel_close: * @ioc: the channel object - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Close the channel, flushing any pending I/O * @@ -327,7 +327,7 @@ int qio_channel_close(QIOChannel *ioc, * qio_channel_shutdown: * @ioc: the channel object * @how: the direction to shutdown - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Shutdowns transmission and/or receiving of data * without closing the underlying transport. @@ -403,7 +403,7 @@ void qio_channel_set_cork(QIOChannel *ioc, * @ioc: the channel object * @offset: the position to seek to, relative to @whence * @whence: one of the (POSIX) SEEK_* constants listed below - * @errp: pointer to an uninitialized error object + * @errp: pointer to a NULL-initialized error object * * Moves the current I/O position within the channel * @ioc, to be @offset. The value of @offset is diff --git a/io/channel-command.c b/io/channel-command.c index 598fdab5a3..a9c67aa221 100644 --- a/io/channel-command.c +++ b/io/channel-command.c @@ -66,7 +66,7 @@ qio_channel_command_new_spawn(const char *const argv[], if (stdinnull || stdoutnull) { devnull = open("/dev/null", O_RDWR); - if (!devnull) { + if (devnull < 0) { error_setg_errno(errp, errno, "Unable to open /dev/null"); goto error; @@ -98,6 +98,9 @@ qio_channel_command_new_spawn(const char *const argv[], close(stdoutfd[0]); close(stdoutfd[1]); } + if (devnull != -1) { + close(devnull); + } execv(argv[0], (char * const *)argv); _exit(1); @@ -117,6 +120,9 @@ qio_channel_command_new_spawn(const char *const argv[], return ioc; error: + if (devnull != -1) { + close(devnull); + } if (stdinfd[0] != -1) { close(stdinfd[0]); } @@ -179,6 +185,7 @@ static int qio_channel_command_abort(QIOChannelCommand *ioc, (unsigned long long)ioc->pid); return -1; } + step++; usleep(10 * 1000); goto rewait; } @@ -201,12 +208,12 @@ static void qio_channel_command_finalize(Object *obj) QIOChannelCommand *ioc = QIO_CHANNEL_COMMAND(obj); if (ioc->readfd != -1) { close(ioc->readfd); - ioc->readfd = -1; } - if (ioc->writefd != -1) { + if (ioc->writefd != -1 && + ioc->writefd != ioc->readfd) { close(ioc->writefd); - ioc->writefd = -1; } + ioc->writefd = ioc->readfd = -1; if (ioc->pid > 0) { #ifndef WIN32 qio_channel_command_abort(ioc, NULL); @@ -298,12 +305,16 @@ static int qio_channel_command_close(QIOChannel *ioc, /* We close FDs before killing, because that * gives a better chance of clean shutdown */ - if (close(cioc->writefd) < 0) { + if (cioc->readfd != -1 && + close(cioc->readfd) < 0) { rv = -1; } - if (close(cioc->readfd) < 0) { + if (cioc->writefd != -1 && + cioc->writefd != cioc->readfd && + close(cioc->writefd) < 0) { rv = -1; } + cioc->writefd = cioc->readfd = -1; #ifndef WIN32 if (qio_channel_command_abort(cioc, errp) < 0) { return -1; diff --git a/io/channel-socket.c b/io/channel-socket.c index 10a5b3136e..bc117b1115 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -449,6 +449,8 @@ static ssize_t qio_channel_socket_readv(QIOChannel *ioc, char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)]; int sflags = 0; + memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)); + #ifdef MSG_CMSG_CLOEXEC sflags |= MSG_CMSG_CLOEXEC; #endif @@ -493,16 +495,18 @@ static ssize_t qio_channel_socket_writev(QIOChannel *ioc, QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); ssize_t ret; struct msghdr msg = { NULL, }; - char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)] = { 0 }; + char control[CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)]; size_t fdsize = sizeof(int) * nfds; struct cmsghdr *cmsg; + memset(control, 0, CMSG_SPACE(sizeof(int) * SOCKET_MAX_FDS)); + msg.msg_iov = (struct iovec *)iov; msg.msg_iovlen = niov; if (nfds) { if (nfds > SOCKET_MAX_FDS) { - error_setg_errno(errp, -EINVAL, + error_setg_errno(errp, EINVAL, "Only %d FDs can be sent, got %zu", SOCKET_MAX_FDS, nfds); return -1;