diff options
author | Orit Wasserman <owasserm@redhat.com> | 2012-09-24 13:11:09 +0200 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2012-09-25 19:05:56 -0500 |
commit | 233aa5c2d1cf4655ffe335025a68cf5454f87dad (patch) | |
tree | 8a772e4cd7a5a48d7f4abc49eef1e08e7622e11e /migration-tcp.c | |
parent | 5db5f44cb4b7f24b9e0efdefc9015e36b7c34881 (diff) | |
download | qemu-233aa5c2d1cf4655ffe335025a68cf5454f87dad.zip qemu-233aa5c2d1cf4655ffe335025a68cf5454f87dad.tar.gz qemu-233aa5c2d1cf4655ffe335025a68cf5454f87dad.tar.bz2 |
Fix address handling in inet_nonblocking_connect
getaddrinfo can give us a list of addresses, but we only try to
connect to the first one. If that fails we never proceed to
the next one. This is common on desktop setups that often have ipv6
configured but not actually working.
To fix this make inet_connect_nonblocking retry connection with a different
address.
callers on inet_nonblocking_connect register a callback function that will
be called when connect opertion completes, in case of failure the fd will have
a negative value
Signed-off-by: Orit Wasserman <owasserm@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'migration-tcp.c')
-rw-r--r-- | migration-tcp.c | 37 |
1 files changed, 9 insertions, 28 deletions
diff --git a/migration-tcp.c b/migration-tcp.c index 7f6ad98..a15c2b8 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -53,54 +53,35 @@ static int tcp_close(MigrationState *s) return r; } -static void tcp_wait_for_connect(void *opaque) +static void tcp_wait_for_connect(int fd, void *opaque) { MigrationState *s = opaque; - int val, ret; - socklen_t valsize = sizeof(val); - DPRINTF("connect completed\n"); - do { - ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize); - } while (ret == -1 && (socket_error()) == EINTR); - - if (ret < 0) { + if (fd < 0) { + DPRINTF("migrate connect error\n"); + s->fd = -1; migrate_fd_error(s); - return; - } - - qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); - - if (val == 0) + } else { + DPRINTF("migrate connect success\n"); + s->fd = fd; migrate_fd_connect(s); - else { - DPRINTF("error connecting %d\n", val); - migrate_fd_error(s); } } int tcp_start_outgoing_migration(MigrationState *s, const char *host_port, Error **errp) { - bool in_progress; - s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; - s->fd = inet_nonblocking_connect(host_port, &in_progress, errp); + s->fd = inet_nonblocking_connect(host_port, tcp_wait_for_connect, s, + errp); if (error_is_set(errp)) { migrate_fd_error(s); return -1; } - if (in_progress) { - DPRINTF("connect in progress\n"); - qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); - } else { - migrate_fd_connect(s); - } - return 0; } |