[PATCH lib/libxtrans] If Socket is getting interrupted with signal EINTR, after re attempts we are closing socket connection, which is wrong.
Arvind Umrao
arvind.umrao at oracle.com
Fri Sep 21 02:02:27 PDT 2012
Could I get approvals for change in behavior of socket, when interrupted
with signal ENTR? I have tested my fixes in Solaris and Ubuntu. My code
changes are not breaking anything. Mark Kettenis, suggest me to fix
caller function also, for eg libICE/src/connect.c:ConnectToPeer() and I
will do it.
Thanks and Regards
-Arvind
On 08/27/12 12:45 PM, Arvind Umrao wrote:
> Code changes are integrated in Solaris and now I am trying to give back to
> community. If Socket is getting interrupted with signal EINTR, we should keep
> socket in progress state(TRANS_IN_PROGRESS) instead of trying again to
> connect(TRANS_TRY_CONNECT_AGAIN). When we close the socket connection on signal
> EINTR and retry, we will end up in same old state and stuck in loop. As per
> documentation if Connect() is interrupted by a signal that is caught, while
> blocked waiting to establish a connection, connect() shall fail and set
> connect() to [EINTR], but the connection request shall not be aborted, and the
> connection shall be established asynchronously. When the connection has been
> established asynchronously, select() and poll() shall indicate that the file
> descriptor for the socket is ready for writing.
>
> For both blocking and non blocking, if connect()interrupted with Signal EINTR,
> it should return TRANS_IN_PROGRESS. In Unix Network Programming, volume 1,
> section 5.9, W. Richard Stevens states:
> What we are doing […] is restarting the interrupted system call ourself.
> This is fine for accept, along with the functions such as read, write, select
> and open. But there is one function that we cannot restart ourself: connect. If
> this function returns EINTR, we cannot call it again, as doing so will return
> an immediate error. When connect is interrupted by a caught signal and is not
> automatically restarted, we must call "Select" to wait for the connection to
> complete, as we describe in section 15.3.
>
> Refer http://www.madore.org/~david/computers/connect-intr.html
>
> Signed-off-by: Arvind Umrao<arvind.umrao at oracle.com>
> ---
> Xtranssock.c | 12 +++++-------
> 1 file changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/Xtranssock.c b/Xtranssock.c
> index dfa41cf..eaef6f0 100644
> --- a/Xtranssock.c
> +++ b/Xtranssock.c
> @@ -1717,7 +1717,7 @@ TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
> * was non-blocking and we should poll using select
> *
> * If the error was EINTR, the connect was interrupted and we
> - * should try again.
> + * should poll using select.
> *
> * If multiple addresses are found for a host then we should
> * try to connect again with a different address for a larger
> @@ -1727,7 +1727,7 @@ TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
> * only affect one of a set of addresses.
> */
>
> - if (olderrno == ECONNREFUSED || olderrno == EINTR
> + if (olderrno == ECONNREFUSED
> #if defined(IPv6)&& defined(AF_INET6)
> || (((addrlist->addr->ai_next != NULL) ||
> (addrlist->addr != addrlist->firstaddr))&&
> @@ -1740,7 +1740,7 @@ TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
> #endif
> )
> res = TRANS_TRY_CONNECT_AGAIN;
> - else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
> + else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS || olderrno == EINTR)
> res = TRANS_IN_PROGRESS;
> else
> {
> @@ -2022,13 +2022,11 @@ TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
> * was non-blocking and we should poll using select
> *
> * If the error was EINTR, the connect was interrupted and we
> - * should try again.
> + * should poll using select.
> */
>
> - if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
> + if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS || olderrno == EINTR)
> return TRANS_IN_PROGRESS;
> - else if (olderrno == EINTR)
> - return TRANS_TRY_CONNECT_AGAIN;
> else if (olderrno == ENOENT || olderrno == ECONNREFUSED) {
> /* If opening as abstract socket failed, try again normally */
> if (abstract) {
More information about the xorg-devel
mailing list