|
@@ -26,7 +26,6 @@
|
|
#include "qemu/sockets.h"
|
|
#include "qemu/sockets.h"
|
|
#include "trace.h"
|
|
#include "trace.h"
|
|
|
|
|
|
-#ifndef WIN32
|
|
|
|
/**
|
|
/**
|
|
* qio_channel_command_new_pid:
|
|
* qio_channel_command_new_pid:
|
|
* @writefd: the FD connected to the command's stdin
|
|
* @writefd: the FD connected to the command's stdin
|
|
@@ -60,7 +59,13 @@ qio_channel_command_new_pid(int writefd,
|
|
ioc->writefd = writefd;
|
|
ioc->writefd = writefd;
|
|
ioc->pid = pid;
|
|
ioc->pid = pid;
|
|
|
|
|
|
- trace_qio_channel_command_new_pid(ioc, writefd, readfd, pid);
|
|
|
|
|
|
+ trace_qio_channel_command_new_pid(ioc, writefd, readfd,
|
|
|
|
+#ifdef WIN32
|
|
|
|
+ GetProcessId(pid)
|
|
|
|
+#else
|
|
|
|
+ pid
|
|
|
|
+#endif
|
|
|
|
+ );
|
|
return ioc;
|
|
return ioc;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -89,18 +94,6 @@ qio_channel_command_new_spawn(const char *const argv[],
|
|
return qio_channel_command_new_pid(stdinfd, stdoutfd, pid);
|
|
return qio_channel_command_new_pid(stdinfd, stdoutfd, pid);
|
|
}
|
|
}
|
|
|
|
|
|
-#else /* WIN32 */
|
|
|
|
-QIOChannelCommand *
|
|
|
|
-qio_channel_command_new_spawn(const char *const argv[],
|
|
|
|
- int flags,
|
|
|
|
- Error **errp)
|
|
|
|
-{
|
|
|
|
- error_setg_errno(errp, ENOSYS,
|
|
|
|
- "Command spawn not supported on this platform");
|
|
|
|
- return NULL;
|
|
|
|
-}
|
|
|
|
-#endif /* WIN32 */
|
|
|
|
-
|
|
|
|
#ifndef WIN32
|
|
#ifndef WIN32
|
|
static int qio_channel_command_abort(QIOChannelCommand *ioc,
|
|
static int qio_channel_command_abort(QIOChannelCommand *ioc,
|
|
Error **errp)
|
|
Error **errp)
|
|
@@ -143,6 +136,23 @@ static int qio_channel_command_abort(QIOChannelCommand *ioc,
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+#else
|
|
|
|
+static int qio_channel_command_abort(QIOChannelCommand *ioc,
|
|
|
|
+ Error **errp)
|
|
|
|
+{
|
|
|
|
+ DWORD ret;
|
|
|
|
+
|
|
|
|
+ TerminateProcess(ioc->pid, 0);
|
|
|
|
+ ret = WaitForSingleObject(ioc->pid, 1000);
|
|
|
|
+ if (ret != WAIT_OBJECT_0) {
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "Process %llu refused to die",
|
|
|
|
+ (unsigned long long)GetProcessId(ioc->pid));
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
#endif /* ! WIN32 */
|
|
#endif /* ! WIN32 */
|
|
|
|
|
|
|
|
|
|
@@ -166,13 +176,27 @@ static void qio_channel_command_finalize(Object *obj)
|
|
}
|
|
}
|
|
ioc->writefd = ioc->readfd = -1;
|
|
ioc->writefd = ioc->readfd = -1;
|
|
if (ioc->pid > 0) {
|
|
if (ioc->pid > 0) {
|
|
-#ifndef WIN32
|
|
|
|
qio_channel_command_abort(ioc, NULL);
|
|
qio_channel_command_abort(ioc, NULL);
|
|
-#endif
|
|
|
|
g_spawn_close_pid(ioc->pid);
|
|
g_spawn_close_pid(ioc->pid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#ifdef WIN32
|
|
|
|
+static bool win32_fd_poll(int fd, gushort events)
|
|
|
|
+{
|
|
|
|
+ GPollFD pfd = { .fd = _get_osfhandle(fd), .events = events };
|
|
|
|
+ int res;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ res = g_poll(&pfd, 1, 0);
|
|
|
|
+ } while (res < 0 && errno == EINTR);
|
|
|
|
+ if (res == 0) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
|
|
static ssize_t qio_channel_command_readv(QIOChannel *ioc,
|
|
static ssize_t qio_channel_command_readv(QIOChannel *ioc,
|
|
const struct iovec *iov,
|
|
const struct iovec *iov,
|
|
@@ -184,6 +208,12 @@ static ssize_t qio_channel_command_readv(QIOChannel *ioc,
|
|
QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
|
|
QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
|
|
ssize_t ret;
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
+#ifdef WIN32
|
|
|
|
+ if (!cioc->blocking && !win32_fd_poll(cioc->readfd, G_IO_IN)) {
|
|
|
|
+ return QIO_CHANNEL_ERR_BLOCK;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+
|
|
retry:
|
|
retry:
|
|
ret = readv(cioc->readfd, iov, niov);
|
|
ret = readv(cioc->readfd, iov, niov);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
@@ -213,6 +243,12 @@ static ssize_t qio_channel_command_writev(QIOChannel *ioc,
|
|
QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
|
|
QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
|
|
ssize_t ret;
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
+#ifdef WIN32
|
|
|
|
+ if (!cioc->blocking && !win32_fd_poll(cioc->writefd, G_IO_OUT)) {
|
|
|
|
+ return QIO_CHANNEL_ERR_BLOCK;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
+
|
|
retry:
|
|
retry:
|
|
ret = writev(cioc->writefd, iov, niov);
|
|
ret = writev(cioc->writefd, iov, niov);
|
|
if (ret <= 0) {
|
|
if (ret <= 0) {
|
|
@@ -233,14 +269,14 @@ static int qio_channel_command_set_blocking(QIOChannel *ioc,
|
|
bool enabled,
|
|
bool enabled,
|
|
Error **errp)
|
|
Error **errp)
|
|
{
|
|
{
|
|
|
|
+ QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
|
|
|
|
+
|
|
#ifdef WIN32
|
|
#ifdef WIN32
|
|
- /* command spawn is not supported on win32 */
|
|
|
|
- g_assert_not_reached();
|
|
|
|
|
|
+ cioc->blocking = enabled;
|
|
#else
|
|
#else
|
|
- QIOChannelCommand *cioc = QIO_CHANNEL_COMMAND(ioc);
|
|
|
|
|
|
|
|
- if (!g_unix_set_fd_nonblocking(cioc->writefd, !enabled, NULL) ||
|
|
|
|
- !g_unix_set_fd_nonblocking(cioc->readfd, !enabled, NULL)) {
|
|
|
|
|
|
+ if ((cioc->writefd >= 0 && !g_unix_set_fd_nonblocking(cioc->writefd, !enabled, NULL)) ||
|
|
|
|
+ (cioc->readfd >= 0 && !g_unix_set_fd_nonblocking(cioc->readfd, !enabled, NULL))) {
|
|
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
|
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
@@ -281,6 +317,8 @@ static int qio_channel_command_close(QIOChannel *ioc,
|
|
(unsigned long long)cioc->pid);
|
|
(unsigned long long)cioc->pid);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
+#else
|
|
|
|
+ WaitForSingleObject(cioc->pid, INFINITE);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
if (rv < 0) {
|
|
if (rv < 0) {
|