[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v5 2/4] qemu-socket: change inet_connect() to to
From: |
Amos Kong |
Subject: |
Re: [Qemu-devel] [PATCH v5 2/4] qemu-socket: change inet_connect() to to support nonblock socket |
Date: |
Tue, 27 Mar 2012 22:36:48 -0400 (EDT) |
----- Original Message -----
> ----- Original Message -----
> > On 03/22/2012 05:52 AM, Amos Kong wrote:
> > > Change inet_connect(const char *str, int socktype) to
> > > inet_connect(const char *str, bool block),
> > > socktype is unused, block is used to assign if set socket
> > > to block/nonblock.
> > > Retry to connect when -EINTR/-EWOULDBLOCK is got.
> > > Connect's successful for nonblock socket when following
> > > errors are got:
> > > -EINPROGRESS
> > > -WSAEALREADY/-WSAEINVAL (win32)
Retry to connect when -EINTR(win32 & posix)/-EWOULDBLOCK(only win32) is
got.
Connect's successful for nonblock socket when following
errors are got:
-EINPROGRESS
-WSAEALREADY(win32)
Discussed with <mdroth> in IRC.
For win32, need to re-connect when EWOULDBLOCK is got.
(http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx)
For posix, it's safe to treat it as fail, otherwise,
it might hang qemu on the order of seconds. (man 2 connect : EAGAIN)
For non-blocking socket, EINPROGRESS maybe got in (win32 & posix),
but WSAEALREADY can only be got after re-connecting
(EWOULDBLOCK is got in first connecting)
Please correct me if something is wrong, thanks.
...
> > > for (e = res; e != NULL; e = e->ai_next) {
> > > @@ -241,21 +248,44 @@ int inet_connect_opts(QemuOpts *opts)
> > > continue;
> > > }
> > > setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on));
> > > -
> > > + if (!block) {
> > > + socket_set_nonblock(sock);
> > > + }
> > > /* connect to peer */
> > > - if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
> > > - if (NULL == e->ai_next)
> > > - fprintf(stderr, "%s: connect(%s,%s,%s,%s):
> > > %s\n",
> > > __FUNCTION__,
> > > - inet_strfamily(e->ai_family),
> > > - e->ai_canonname, uaddr, uport,
> > > strerror(errno));
> > > - closesocket(sock);
> > > - continue;
> > > + do {
> > > + err = 0;
> > > + if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) {
> > > + err = -socket_error();
> > > + }
> > > + } while (err == -EINTR || err == -EWOULDBLOCK);
> > > +
> >
> > this is only relevant for non blocking socket
>
> For blocking socket, if connect() is interrupted by a signal
> that is caught while blocked waiting to establish a connection,
> connect() shall fail and set errno to [EINTR]
> So just re-connect when EINTR/EWOULDBLOCK are set.
>
> http://marc.info/?l=kvm&m=133238606300535&w=2
>
>
> > it should look something like this :
> >
> > while ( (rc = connect(sock, e->ai_addr, e->ai_addrlen)) < 0 &&
> > !block
> > &&
> > (socket_error() == EINTR || socket_error() == -EWOULDBLOCK))
>
>
> while ( (rc = connect(sock, e->ai_addr, e->ai_addrlen)) < 0 &&
> (socket_error() == EINTR || socket_error() == EWOULDBLOCK))
> ;
do {
err = 0;
if (rc = connect(sock, e->ai_addr, e->ai_addrlen) < 0) {
err = -socket_error();
}
#ifndef _WIN32
} while (err == -EINTR || err == -EWOULDBLOCK);
#else
} while (err == -EINTR);
#endif
if (rc >= 0) {
goto success;
} else if (!block && err == -EINPROGRESS) {
goto success;
#ifndef _WIN32
} else if (!block && err == -WSAEALREADY) {
goto success;
#endif
}
> > > + if (err >= 0) {
> > > + goto success;
> > > + } else if (!block && err == -EINPROGRESS) {
> > > + goto success;
> > > +#ifdef _WIN32
> > > + } else if (!block && (err == -WSAEALREADY || err ==
> > > -WSAEINVAL)) {
> > > + goto success;
> > > +#endif
> >
> > I prefer to check for error the code should look:
> >
> > if (rc < 0 && (block ||
> > #ifdef _WIN32
> > (socket_error() != WSAEALREADY && socket_error() !=
> > -WSAEINVAL))
> > {
> > #else
> > (socket_error() != EINPROGRESS)) {
> > #endif
> > if (NULL == e->ai_next)
> > fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n",
> > __func__,
> > inet_strfamily(e->ai_family),
> > e->ai_canonname, uaddr, uport, strerror(errno));
> > closesocket(sock);
> > continue;
> > }
> > ...
> >
> > Orit
> > > }
> > > - freeaddrinfo(res);
> > > - return sock;
> > > +
> > > + if (NULL == e->ai_next) {
> > > + fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n",
> > > __func__,
> > > + inet_strfamily(e->ai_family),
> > > + e->ai_canonname, uaddr, uport,
> > > strerror(errno));
> > > + }
> > > + closesocket(sock);
> > > }
> > > freeaddrinfo(res);
>
>
> > > +
> > > +err:
> > > + set_socket_error(-err);
> > > return -1;
>
>
> > > +
> > > +success:
> > > + freeaddrinfo(res);
> > > + set_socket_error(-err);
> > > + return sock;
> > > }
...
- Re: [Qemu-devel] [PATCH v4 1/2] qemu-socket: change inet_connect() to to support nonblock socket, (continued)
- Re: [Qemu-devel] [PATCH v4 1/2] qemu-socket: change inet_connect() to to support nonblock socket, Orit Wasserman, 2012/03/20
- Re: [Qemu-devel] [PATCH v4 1/2] qemu-socket: change inet_connect() to to support nonblock socket, Michael Roth, 2012/03/21
- Re: [Qemu-devel] [PATCH v4 1/2] qemu-socket: change inet_connect() to to support nonblock socket, Amos Kong, 2012/03/21
- [Qemu-devel] [PATCH v5 0/2] support to migrate with IPv6 address, Amos Kong, 2012/03/21
- [Qemu-devel] [PATCH v5 1/4] sockets: introduce set_socket_error(), Amos Kong, 2012/03/21
- Re: [Qemu-devel] [PATCH v5 1/4] sockets: introduce set_socket_error(), Orit Wasserman, 2012/03/27
- [Qemu-devel] [PATCH v6 1/4] sockets: introduce set_socket_error(), Amos Kong, 2012/03/27
- [Qemu-devel] [PATCH v5 2/4] qemu-socket: change inet_connect() to to support nonblock socket, Amos Kong, 2012/03/21
- Re: [Qemu-devel] [PATCH v5 2/4] qemu-socket: change inet_connect() to to support nonblock socket, Orit Wasserman, 2012/03/27
- Re: [Qemu-devel] [PATCH v5 2/4] qemu-socket: change inet_connect() to to support nonblock socket, Amos Kong, 2012/03/27
- Re: [Qemu-devel] [PATCH v5 2/4] qemu-socket: change inet_connect() to to support nonblock socket,
Amos Kong <=
- [Qemu-devel] [PATCH v5 3/4] sockets: pass back errors in inet_listen(), Amos Kong, 2012/03/21
- Re: [Qemu-devel] [PATCH v5 3/4] sockets: pass back errors in inet_listen(), Michael Roth, 2012/03/27
- [Qemu-devel] [PATCH v5 4/4] use inet_listen()/inet_connect() to support ipv6 migration, Amos Kong, 2012/03/21