e3c68b
From 2c99b7db00a6238fd43053dd672c8ce519d8fd27 Mon Sep 17 00:00:00 2001
e3c68b
From: Xavi Hernandez <xhernandez@redhat.com>
e3c68b
Date: Wed, 11 Dec 2019 18:21:14 +0100
e3c68b
Subject: [PATCH 341/344] socket: fix error handling
e3c68b
e3c68b
When __socket_proto_state_machine() detected a problem in the size of
e3c68b
the request or it couldn't allocate an iobuf of the requested size, it
e3c68b
returned -ENOMEM (-12). However the caller was expecting only -1 in
e3c68b
case of error. For this reason the error passes undetected initially,
e3c68b
adding back the socket to the epoll object. On further processing,
e3c68b
however, the error is finally detected and the connection terminated.
e3c68b
Meanwhile, another thread could receive a poll_in event from the same
e3c68b
connection, which could cause races with the connection destruction.
e3c68b
When this happened, the process crashed.
e3c68b
e3c68b
To fix this, all error detection conditions have been hardened to be
e3c68b
more strict on what is valid and what not. Also, we don't return
e3c68b
-ENOMEM anymore. We always return -1 in case of error.
e3c68b
e3c68b
An additional change has been done to prevent destruction of the
e3c68b
transport object while it may still be needed.
e3c68b
e3c68b
Upstream patch:
e3c68b
> Change-Id: I6e59cd81cbf670f7adfdde942625d4e6c3fbc82d
e3c68b
> Upstream patch link: https://review.gluster.org/c/glusterfs/+/23861
e3c68b
> Fixes: bz#1782495
e3c68b
> Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
e3c68b
e3c68b
Change-Id: I6e59cd81cbf670f7adfdde942625d4e6c3fbc82d
e3c68b
BUG: 1779696
e3c68b
Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/187689
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Raghavendra Gowdappa <rgowdapp@redhat.com>
e3c68b
---
e3c68b
 rpc/rpc-transport/socket/src/socket.c | 173 ++++++++++++++++++----------------
e3c68b
 1 file changed, 90 insertions(+), 83 deletions(-)
e3c68b
e3c68b
diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c
e3c68b
index bf2fa71..f54ca83 100644
e3c68b
--- a/rpc/rpc-transport/socket/src/socket.c
e3c68b
+++ b/rpc/rpc-transport/socket/src/socket.c
e3c68b
@@ -173,7 +173,7 @@ ssl_setup_connection_params(rpc_transport_t *this);
e3c68b
                                                                                \
e3c68b
         ret = __socket_readv(this, in->pending_vector, 1, &in->pending_vector, \
e3c68b
                              &in->pending_count, &bytes_read);                 \
e3c68b
-        if (ret == -1)                                                         \
e3c68b
+        if (ret < 0)                                                           \
e3c68b
             break;                                                             \
e3c68b
         __socket_proto_update_priv_after_read(priv, ret, bytes_read);          \
e3c68b
     }
e3c68b
@@ -739,7 +739,7 @@ __socket_rwv(rpc_transport_t *this, struct iovec *vector, int count,
e3c68b
                 ret = sys_writev(sock, opvector, IOV_MIN(opcount));
e3c68b
             }
e3c68b
 
e3c68b
-            if (ret == 0 || (ret == -1 && errno == EAGAIN)) {
e3c68b
+            if ((ret == 0) || ((ret < 0) && (errno == EAGAIN))) {
e3c68b
                 /* done for now */
e3c68b
                 break;
e3c68b
             } else if (ret > 0)
e3c68b
@@ -754,7 +754,7 @@ __socket_rwv(rpc_transport_t *this, struct iovec *vector, int count,
e3c68b
                 errno = ENODATA;
e3c68b
                 ret = -1;
e3c68b
             }
e3c68b
-            if (ret == -1 && errno == EAGAIN) {
e3c68b
+            if ((ret < 0) && (errno == EAGAIN)) {
e3c68b
                 /* done for now */
e3c68b
                 break;
e3c68b
             } else if (ret > 0)
e3c68b
@@ -770,7 +770,7 @@ __socket_rwv(rpc_transport_t *this, struct iovec *vector, int count,
e3c68b
             errno = ENOTCONN;
e3c68b
             break;
e3c68b
         }
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret < 0) {
e3c68b
             if (errno == EINTR)
e3c68b
                 continue;
e3c68b
 
e3c68b
@@ -907,7 +907,7 @@ __socket_disconnect(rpc_transport_t *this)
e3c68b
     gf_log(this->name, GF_LOG_TRACE, "disconnecting %p, sock=%d", this,
e3c68b
            priv->sock);
e3c68b
 
e3c68b
-    if (priv->sock != -1) {
e3c68b
+    if (priv->sock >= 0) {
e3c68b
         gf_log_callingfn(this->name, GF_LOG_TRACE,
e3c68b
                          "tearing down socket connection");
e3c68b
         ret = __socket_teardown_connection(this);
e3c68b
@@ -942,7 +942,7 @@ __socket_server_bind(rpc_transport_t *this)
e3c68b
 
e3c68b
     ret = setsockopt(priv->sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
e3c68b
 
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log(this->name, GF_LOG_ERROR,
e3c68b
                "setsockopt() for SO_REUSEADDR failed (%s)", strerror(errno));
e3c68b
     }
e3c68b
@@ -955,7 +955,7 @@ __socket_server_bind(rpc_transport_t *this)
e3c68b
         if (reuse_check_sock >= 0) {
e3c68b
             ret = connect(reuse_check_sock, SA(&unix_addr),
e3c68b
                           this->myinfo.sockaddr_len);
e3c68b
-            if ((ret == -1) && (ECONNREFUSED == errno)) {
e3c68b
+            if ((ret != 0) && (ECONNREFUSED == errno)) {
e3c68b
                 sys_unlink(((struct sockaddr_un *)&unix_addr)->sun_path);
e3c68b
             }
e3c68b
             gf_log(this->name, GF_LOG_INFO,
e3c68b
@@ -967,7 +967,7 @@ __socket_server_bind(rpc_transport_t *this)
e3c68b
     ret = bind(priv->sock, (struct sockaddr *)&this->myinfo.sockaddr,
e3c68b
                this->myinfo.sockaddr_len);
e3c68b
 
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log(this->name, GF_LOG_ERROR, "binding to %s failed: %s",
e3c68b
                this->myinfo.identifier, strerror(errno));
e3c68b
         if (errno == EADDRINUSE) {
e3c68b
@@ -976,7 +976,7 @@ __socket_server_bind(rpc_transport_t *this)
e3c68b
     }
e3c68b
     if (AF_UNIX != SA(&this->myinfo.sockaddr)->sa_family) {
e3c68b
         if (getsockname(priv->sock, SA(&this->myinfo.sockaddr),
e3c68b
-                        &this->myinfo.sockaddr_len) == -1) {
e3c68b
+                        &this->myinfo.sockaddr_len) != 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING,
e3c68b
                    "getsockname on (%d) failed (%s)", priv->sock,
e3c68b
                    strerror(errno));
e3c68b
@@ -1004,7 +1004,7 @@ __socket_nonblock(int fd)
e3c68b
 
e3c68b
     flags = fcntl(fd, F_GETFL);
e3c68b
 
e3c68b
-    if (flags != -1)
e3c68b
+    if (flags >= 0)
e3c68b
         ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
e3c68b
 
e3c68b
     return ret;
e3c68b
@@ -1034,7 +1034,7 @@ __socket_keepalive(int fd, int family, int keepaliveintvl, int keepaliveidle,
e3c68b
 #endif
e3c68b
 
e3c68b
     ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log("socket", GF_LOG_WARNING,
e3c68b
                "failed to set keep alive option on socket %d", fd);
e3c68b
         goto err;
e3c68b
@@ -1051,7 +1051,7 @@ __socket_keepalive(int fd, int family, int keepaliveintvl, int keepaliveidle,
e3c68b
     ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &keepaliveintvl,
e3c68b
                      sizeof(keepaliveintvl));
e3c68b
 #endif
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log("socket", GF_LOG_WARNING,
e3c68b
                "failed to set keep alive interval on socket %d", fd);
e3c68b
         goto err;
e3c68b
@@ -1062,7 +1062,7 @@ __socket_keepalive(int fd, int family, int keepaliveintvl, int keepaliveidle,
e3c68b
 
e3c68b
     ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepaliveidle,
e3c68b
                      sizeof(keepaliveidle));
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log("socket", GF_LOG_WARNING,
e3c68b
                "failed to set keep idle %d on socket %d, %s", keepaliveidle, fd,
e3c68b
                strerror(errno));
e3c68b
@@ -1070,7 +1070,7 @@ __socket_keepalive(int fd, int family, int keepaliveintvl, int keepaliveidle,
e3c68b
     }
e3c68b
     ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveintvl,
e3c68b
                      sizeof(keepaliveintvl));
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log("socket", GF_LOG_WARNING,
e3c68b
                "failed to set keep interval %d on socket %d, %s",
e3c68b
                keepaliveintvl, fd, strerror(errno));
e3c68b
@@ -1082,7 +1082,7 @@ __socket_keepalive(int fd, int family, int keepaliveintvl, int keepaliveidle,
e3c68b
         goto done;
e3c68b
     ret = setsockopt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout_ms,
e3c68b
                      sizeof(timeout_ms));
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log("socket", GF_LOG_WARNING,
e3c68b
                "failed to set "
e3c68b
                "TCP_USER_TIMEOUT %d on socket %d, %s",
e3c68b
@@ -1093,7 +1093,7 @@ __socket_keepalive(int fd, int family, int keepaliveintvl, int keepaliveidle,
e3c68b
 #if defined(TCP_KEEPCNT)
e3c68b
     ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepalivecnt,
e3c68b
                      sizeof(keepalivecnt));
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret != 0) {
e3c68b
         gf_log("socket", GF_LOG_WARNING,
e3c68b
                "failed to set "
e3c68b
                "TCP_KEEPCNT %d on socket %d, %s",
e3c68b
@@ -1366,7 +1366,7 @@ socket_event_poll_err(rpc_transport_t *this, int gen, int idx)
e3c68b
 
e3c68b
     pthread_mutex_lock(&priv->out_lock);
e3c68b
     {
e3c68b
-        if ((priv->gen == gen) && (priv->idx == idx) && (priv->sock != -1)) {
e3c68b
+        if ((priv->gen == gen) && (priv->idx == idx) && (priv->sock >= 0)) {
e3c68b
             __socket_ioq_flush(this);
e3c68b
             __socket_reset(this);
e3c68b
             socket_closed = _gf_true;
e3c68b
@@ -1405,7 +1405,7 @@ socket_event_poll_out(rpc_transport_t *this)
e3c68b
         if (priv->connected == 1) {
e3c68b
             ret = __socket_ioq_churn(this);
e3c68b
 
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret < 0) {
e3c68b
                 gf_log(this->name, GF_LOG_TRACE,
e3c68b
                        "__socket_ioq_churn returned -1; "
e3c68b
                        "disconnecting socket");
e3c68b
@@ -1463,7 +1463,7 @@ __socket_read_simple_msg(rpc_transport_t *this)
e3c68b
                                      &bytes_read);
e3c68b
             }
e3c68b
 
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret < 0) {
e3c68b
                 gf_log(this->name, GF_LOG_WARNING,
e3c68b
                        "reading from socket failed. Error (%s), "
e3c68b
                        "peer (%s)",
e3c68b
@@ -1661,8 +1661,8 @@ __socket_read_vectored_request(rpc_transport_t *this,
e3c68b
 
e3c68b
             remaining_size = RPC_FRAGSIZE(in->fraghdr) - frag->bytes_read;
e3c68b
 
e3c68b
-            if ((ret == -1) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
-                                RPC_LASTFRAG(in->fraghdr))) {
e3c68b
+            if ((ret < 0) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
+                              RPC_LASTFRAG(in->fraghdr))) {
e3c68b
                 request->vector_state = SP_STATE_VECTORED_REQUEST_INIT;
e3c68b
                 in->payload_vector.iov_len = ((unsigned long)frag->fragcurrent -
e3c68b
                                               (unsigned long)
e3c68b
@@ -1739,8 +1739,8 @@ __socket_read_request(rpc_transport_t *this)
e3c68b
 
e3c68b
             remaining_size = RPC_FRAGSIZE(in->fraghdr) - frag->bytes_read;
e3c68b
 
e3c68b
-            if ((ret == -1) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
-                                (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
+            if ((ret < 0) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
+                              (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
                 request->header_state = SP_STATE_REQUEST_HEADER_INIT;
e3c68b
             }
e3c68b
 
e3c68b
@@ -1870,8 +1870,8 @@ __socket_read_accepted_successful_reply(rpc_transport_t *this)
e3c68b
             /* now read the entire remaining msg into new iobuf */
e3c68b
             ret = __socket_read_simple_msg(this);
e3c68b
             remaining_size = RPC_FRAGSIZE(in->fraghdr) - frag->bytes_read;
e3c68b
-            if ((ret == -1) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
-                                RPC_LASTFRAG(in->fraghdr))) {
e3c68b
+            if ((ret < 0) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
+                              RPC_LASTFRAG(in->fraghdr))) {
e3c68b
                 frag->call_body.reply.accepted_success_state =
e3c68b
                     SP_STATE_ACCEPTED_SUCCESS_REPLY_INIT;
e3c68b
             }
e3c68b
@@ -2003,8 +2003,8 @@ __socket_read_accepted_successful_reply_v2(rpc_transport_t *this)
e3c68b
             /* now read the entire remaining msg into new iobuf */
e3c68b
             ret = __socket_read_simple_msg(this);
e3c68b
             remaining_size = RPC_FRAGSIZE(in->fraghdr) - frag->bytes_read;
e3c68b
-            if ((ret == -1) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
-                                RPC_LASTFRAG(in->fraghdr))) {
e3c68b
+            if ((ret < 0) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
+                              RPC_LASTFRAG(in->fraghdr))) {
e3c68b
                 frag->call_body.reply.accepted_success_state =
e3c68b
                     SP_STATE_ACCEPTED_SUCCESS_REPLY_INIT;
e3c68b
             }
e3c68b
@@ -2103,8 +2103,8 @@ __socket_read_accepted_reply(rpc_transport_t *this)
e3c68b
 
e3c68b
             remaining_size = RPC_FRAGSIZE(in->fraghdr) - frag->bytes_read;
e3c68b
 
e3c68b
-            if ((ret == -1) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
-                                (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
+            if ((ret < 0) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
+                              (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
                 frag->call_body.reply
e3c68b
                     .accepted_state = SP_STATE_ACCEPTED_REPLY_INIT;
e3c68b
             }
e3c68b
@@ -2169,8 +2169,8 @@ __socket_read_vectored_reply(rpc_transport_t *this)
e3c68b
 
e3c68b
             remaining_size = RPC_FRAGSIZE(in->fraghdr) - frag->bytes_read;
e3c68b
 
e3c68b
-            if ((ret == -1) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
-                                (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
+            if ((ret < 0) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
+                              (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
                 frag->call_body.reply
e3c68b
                     .status_state = SP_STATE_VECTORED_REPLY_STATUS_INIT;
e3c68b
                 in->payload_vector.iov_len = (unsigned long)frag->fragcurrent -
e3c68b
@@ -2237,7 +2237,7 @@ __socket_read_reply(rpc_transport_t *this)
e3c68b
         /* Transition back to externally visible state. */
e3c68b
         frag->state = SP_STATE_READ_MSGTYPE;
e3c68b
 
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret < 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING,
e3c68b
                    "notify for event MAP_XID failed for %s",
e3c68b
                    this->peerinfo.identifier);
e3c68b
@@ -2315,8 +2315,8 @@ __socket_read_frag(rpc_transport_t *this)
e3c68b
 
e3c68b
             remaining_size = RPC_FRAGSIZE(in->fraghdr) - frag->bytes_read;
e3c68b
 
e3c68b
-            if ((ret == -1) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
-                                (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
+            if ((ret < 0) || ((ret == 0) && (remaining_size == 0) &&
e3c68b
+                              (RPC_LASTFRAG(in->fraghdr)))) {
e3c68b
                 /* frag->state = SP_STATE_NADA; */
e3c68b
                 frag->state = SP_STATE_RPCFRAG_INIT;
e3c68b
             }
e3c68b
@@ -2400,7 +2400,7 @@ __socket_proto_state_machine(rpc_transport_t *this,
e3c68b
                 ret = __socket_readv(this, in->pending_vector, 1,
e3c68b
                                      &in->pending_vector, &in->pending_count,
e3c68b
                                      NULL);
e3c68b
-                if (ret == -1)
e3c68b
+                if (ret < 0)
e3c68b
                     goto out;
e3c68b
 
e3c68b
                 if (ret > 0) {
e3c68b
@@ -2422,7 +2422,7 @@ __socket_proto_state_machine(rpc_transport_t *this,
e3c68b
                 in->total_bytes_read += RPC_FRAGSIZE(in->fraghdr);
e3c68b
 
e3c68b
                 if (in->total_bytes_read >= GF_UNIT_GB) {
e3c68b
-                    ret = -ENOMEM;
e3c68b
+                    ret = -1;
e3c68b
                     goto out;
e3c68b
                 }
e3c68b
 
e3c68b
@@ -2430,7 +2430,7 @@ __socket_proto_state_machine(rpc_transport_t *this,
e3c68b
                     this->ctx->iobuf_pool,
e3c68b
                     (in->total_bytes_read + sizeof(in->fraghdr)));
e3c68b
                 if (!iobuf) {
e3c68b
-                    ret = -ENOMEM;
e3c68b
+                    ret = -1;
e3c68b
                     goto out;
e3c68b
                 }
e3c68b
 
e3c68b
@@ -2457,7 +2457,7 @@ __socket_proto_state_machine(rpc_transport_t *this,
e3c68b
             case SP_STATE_READING_FRAG:
e3c68b
                 ret = __socket_read_frag(this);
e3c68b
 
e3c68b
-                if ((ret == -1) ||
e3c68b
+                if ((ret < 0) ||
e3c68b
                     (frag->bytes_read != RPC_FRAGSIZE(in->fraghdr))) {
e3c68b
                     goto out;
e3c68b
                 }
e3c68b
@@ -2575,7 +2575,7 @@ socket_event_poll_in(rpc_transport_t *this, gf_boolean_t notify_handled)
e3c68b
         pthread_mutex_unlock(&priv->notify.lock);
e3c68b
     }
e3c68b
 
e3c68b
-    if (notify_handled && (ret != -1))
e3c68b
+    if (notify_handled && (ret >= 0))
e3c68b
         event_handled(ctx->event_pool, priv->sock, priv->idx, priv->gen);
e3c68b
 
e3c68b
     if (pollin) {
e3c68b
@@ -2618,10 +2618,10 @@ socket_connect_finish(rpc_transport_t *this)
e3c68b
 
e3c68b
         ret = __socket_connect_finish(priv->sock);
e3c68b
 
e3c68b
-        if (ret == -1 && errno == EINPROGRESS)
e3c68b
+        if ((ret < 0) && (errno == EINPROGRESS))
e3c68b
             ret = 1;
e3c68b
 
e3c68b
-        if (ret == -1 && errno != EINPROGRESS) {
e3c68b
+        if ((ret < 0) && (errno != EINPROGRESS)) {
e3c68b
             if (!priv->connect_finish_log) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR,
e3c68b
                        "connection to %s failed (%s); "
e3c68b
@@ -2640,7 +2640,7 @@ socket_connect_finish(rpc_transport_t *this)
e3c68b
 
e3c68b
             ret = getsockname(priv->sock, SA(&this->myinfo.sockaddr),
e3c68b
                               &this->myinfo.sockaddr_len);
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_WARNING,
e3c68b
                        "getsockname on (%d) failed (%s) - "
e3c68b
                        "disconnecting socket",
e3c68b
@@ -2924,6 +2924,13 @@ socket_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
         return;
e3c68b
     }
e3c68b
 
e3c68b
+    /* At this point we are sure no other thread is using the transport because
e3c68b
+     * we cannot receive more events until we call gf_event_handled(). However
e3c68b
+     * this function may call gf_event_handled() in some cases. When this is
e3c68b
+     * done, the transport may be destroyed at any moment if another thread
e3c68b
+     * handled an error event. To prevent that we take a reference here. */
e3c68b
+    rpc_transport_ref(this);
e3c68b
+
e3c68b
     GF_VALIDATE_OR_GOTO("socket", this, out);
e3c68b
     GF_VALIDATE_OR_GOTO("socket", this->private, out);
e3c68b
     GF_VALIDATE_OR_GOTO("socket", this->xl, out);
e3c68b
@@ -2960,7 +2967,7 @@ socket_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
             if (ret > 0) {
e3c68b
                 gf_log(this->name, GF_LOG_TRACE,
e3c68b
                        "(sock:%d) returning to wait on socket", priv->sock);
e3c68b
-                return;
e3c68b
+                goto out;
e3c68b
             }
e3c68b
         } else {
e3c68b
             char *sock_type = (priv->is_server ? "Server" : "Client");
e3c68b
@@ -3015,7 +3022,7 @@ socket_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
     }
e3c68b
 
e3c68b
 out:
e3c68b
-    return;
e3c68b
+    rpc_transport_unref(this);
e3c68b
 }
e3c68b
 
e3c68b
 static void
e3c68b
@@ -3074,7 +3081,7 @@ socket_server_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
 
e3c68b
         event_handled(ctx->event_pool, fd, idx, gen);
e3c68b
 
e3c68b
-        if (new_sock == -1) {
e3c68b
+        if (new_sock < 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING, "accept on %d failed (%s)",
e3c68b
                    priv->sock, strerror(errno));
e3c68b
             goto out;
e3c68b
@@ -3082,7 +3089,7 @@ socket_server_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
 
e3c68b
         if (priv->nodelay && (new_sockaddr.ss_family != AF_UNIX)) {
e3c68b
             ret = __socket_nodelay(new_sock);
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_WARNING,
e3c68b
                        "setsockopt() failed for "
e3c68b
                        "NODELAY (%s)",
e3c68b
@@ -3094,7 +3101,7 @@ socket_server_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
             ret = __socket_keepalive(new_sock, new_sockaddr.ss_family,
e3c68b
                                      priv->keepaliveintvl, priv->keepaliveidle,
e3c68b
                                      priv->keepalivecnt, priv->timeout);
e3c68b
-            if (ret == -1)
e3c68b
+            if (ret != 0)
e3c68b
                 gf_log(this->name, GF_LOG_WARNING,
e3c68b
                        "Failed to set keep-alive: %s", strerror(errno));
e3c68b
         }
e3c68b
@@ -3110,7 +3117,7 @@ socket_server_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
         }
e3c68b
 
e3c68b
         ret = pthread_mutex_init(&new_trans->lock, NULL);
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret != 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING,
e3c68b
                    "pthread_mutex_init() failed: %s; closing newly accepted "
e3c68b
                    "socket %d",
e3c68b
@@ -3130,7 +3137,7 @@ socket_server_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
 
e3c68b
         ret = getsockname(new_sock, SA(&new_trans->myinfo.sockaddr),
e3c68b
                           &new_trans->myinfo.sockaddr_len);
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret != 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING,
e3c68b
                    "getsockname on socket %d "
e3c68b
                    "failed (errno:%s); closing newly accepted socket",
e3c68b
@@ -3237,7 +3244,7 @@ socket_server_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
              */
e3c68b
             ret = rpc_transport_notify(this, RPC_TRANSPORT_ACCEPT, new_trans);
e3c68b
 
e3c68b
-            if (ret != -1) {
e3c68b
+            if (ret >= 0) {
e3c68b
                 new_priv->idx = event_register(
e3c68b
                     ctx->event_pool, new_sock, socket_event_handler, new_trans,
e3c68b
                     1, 0, new_trans->notify_poller_death);
e3c68b
@@ -3275,7 +3282,7 @@ socket_server_event_handler(int fd, int idx, int gen, void *data, int poll_in,
e3c68b
             rpc_transport_unref(new_trans);
e3c68b
         }
e3c68b
 
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret < 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING, "closing newly accepted socket");
e3c68b
             sys_close(new_sock);
e3c68b
             /* this unref is to actually cause the destruction of
e3c68b
@@ -3406,7 +3413,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
 
e3c68b
     pthread_mutex_lock(&priv->out_lock);
e3c68b
     {
e3c68b
-        if (priv->sock != -1) {
e3c68b
+        if (priv->sock >= 0) {
e3c68b
             gf_log_callingfn(this->name, GF_LOG_TRACE,
e3c68b
                              "connect () called on transport "
e3c68b
                              "already connected");
e3c68b
@@ -3420,7 +3427,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
 
e3c68b
         ret = socket_client_get_remote_sockaddr(this, &sock_union.sa,
e3c68b
                                                 &sockaddr_len, &sa_family);
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret < 0) {
e3c68b
             /* logged inside client_get_remote_sockaddr */
e3c68b
             goto unlock;
e3c68b
         }
e3c68b
@@ -3439,7 +3446,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
         this->peerinfo.sockaddr_len = sockaddr_len;
e3c68b
 
e3c68b
         priv->sock = sys_socket(sa_family, SOCK_STREAM, 0);
e3c68b
-        if (priv->sock == -1) {
e3c68b
+        if (priv->sock < 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR, "socket creation failed (%s)",
e3c68b
                    strerror(errno));
e3c68b
             ret = -1;
e3c68b
@@ -3451,7 +3458,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
          */
e3c68b
         if (priv->windowsize != 0) {
e3c68b
             if (setsockopt(priv->sock, SOL_SOCKET, SO_RCVBUF, &priv->windowsize,
e3c68b
-                           sizeof(priv->windowsize)) < 0) {
e3c68b
+                           sizeof(priv->windowsize)) != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR,
e3c68b
                        "setting receive window "
e3c68b
                        "size failed: %d: %d: %s",
e3c68b
@@ -3459,7 +3466,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
             }
e3c68b
 
e3c68b
             if (setsockopt(priv->sock, SOL_SOCKET, SO_SNDBUF, &priv->windowsize,
e3c68b
-                           sizeof(priv->windowsize)) < 0) {
e3c68b
+                           sizeof(priv->windowsize)) != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR,
e3c68b
                        "setting send window size "
e3c68b
                        "failed: %d: %d: %s",
e3c68b
@@ -3484,7 +3491,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
         if (priv->nodelay && (sa_family != AF_UNIX)) {
e3c68b
             ret = __socket_nodelay(priv->sock);
e3c68b
 
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR, "NODELAY on %d failed (%s)",
e3c68b
                        priv->sock, strerror(errno));
e3c68b
             }
e3c68b
@@ -3494,7 +3501,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
             ret = __socket_keepalive(priv->sock, sa_family,
e3c68b
                                      priv->keepaliveintvl, priv->keepaliveidle,
e3c68b
                                      priv->keepalivecnt, priv->timeout);
e3c68b
-            if (ret == -1)
e3c68b
+            if (ret != 0)
e3c68b
                 gf_log(this->name, GF_LOG_ERROR, "Failed to set keep-alive: %s",
e3c68b
                        strerror(errno));
e3c68b
         }
e3c68b
@@ -3516,7 +3523,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
 
e3c68b
         ret = client_bind(this, SA(&this->myinfo.sockaddr),
e3c68b
                           &this->myinfo.sockaddr_len, priv->sock);
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret < 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING, "client bind failed: %s",
e3c68b
                    strerror(errno));
e3c68b
             goto handler;
e3c68b
@@ -3525,7 +3532,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
         /* make socket non-blocking for all types of sockets */
e3c68b
         if (!priv->bio) {
e3c68b
             ret = __socket_nonblock(priv->sock);
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR, "NBIO on %d failed (%s)",
e3c68b
                        priv->sock, strerror(errno));
e3c68b
                 goto handler;
e3c68b
@@ -3552,7 +3559,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
 
e3c68b
         connect_attempted = _gf_true;
e3c68b
 
e3c68b
-        if (ret == -1 && errno == ENOENT && ign_enoent) {
e3c68b
+        if ((ret != 0) && (errno == ENOENT) && ign_enoent) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING,
e3c68b
                    "Ignore failed connection attempt on %s, (%s) ",
e3c68b
                    this->peerinfo.identifier, strerror(errno));
e3c68b
@@ -3570,7 +3577,7 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
             goto handler;
e3c68b
         }
e3c68b
 
e3c68b
-        if (ret == -1 && ((errno != EINPROGRESS) && (errno != ENOENT))) {
e3c68b
+        if ((ret != 0) && (errno != EINPROGRESS) && (errno != ENOENT)) {
e3c68b
             /* For unix path based sockets, the socket path is
e3c68b
              * cryptic (md5sum of path) and may not be useful for
e3c68b
              * the user in debugging so log it in DEBUG
e3c68b
@@ -3634,8 +3641,8 @@ socket_connect(rpc_transport_t *this, int port)
e3c68b
     pthread_mutex_unlock(&priv->out_lock);
e3c68b
 
e3c68b
 err:
e3c68b
-    /* if sock != -1, then cleanup is done from the event handler */
e3c68b
-    if (ret == -1 && sock == -1) {
e3c68b
+    /* if sock >= 0, then cleanup is done from the event handler */
e3c68b
+    if ((ret < 0) && (sock < 0)) {
e3c68b
         /* Cleaup requires to send notification to upper layer which
e3c68b
            intern holds the big_lock. There can be dead-lock situation
e3c68b
            if big_lock is already held by the current thread.
e3c68b
@@ -3689,20 +3696,20 @@ socket_listen(rpc_transport_t *this)
e3c68b
     }
e3c68b
     pthread_mutex_unlock(&priv->out_lock);
e3c68b
 
e3c68b
-    if (sock != -1) {
e3c68b
+    if (sock >= 0) {
e3c68b
         gf_log_callingfn(this->name, GF_LOG_DEBUG, "already listening");
e3c68b
         return ret;
e3c68b
     }
e3c68b
 
e3c68b
     ret = socket_server_get_local_sockaddr(this, SA(&sockaddr), &sockaddr_len,
e3c68b
                                            &sa_family);
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret < 0) {
e3c68b
         return ret;
e3c68b
     }
e3c68b
 
e3c68b
     pthread_mutex_lock(&priv->out_lock);
e3c68b
     {
e3c68b
-        if (priv->sock != -1) {
e3c68b
+        if (priv->sock >= 0) {
e3c68b
             gf_log(this->name, GF_LOG_DEBUG, "already listening");
e3c68b
             goto unlock;
e3c68b
         }
e3c68b
@@ -3712,7 +3719,7 @@ socket_listen(rpc_transport_t *this)
e3c68b
 
e3c68b
         priv->sock = sys_socket(sa_family, SOCK_STREAM, 0);
e3c68b
 
e3c68b
-        if (priv->sock == -1) {
e3c68b
+        if (priv->sock < 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR, "socket creation failed (%s)",
e3c68b
                    strerror(errno));
e3c68b
             goto unlock;
e3c68b
@@ -3723,7 +3730,7 @@ socket_listen(rpc_transport_t *this)
e3c68b
          */
e3c68b
         if (priv->windowsize != 0) {
e3c68b
             if (setsockopt(priv->sock, SOL_SOCKET, SO_RCVBUF, &priv->windowsize,
e3c68b
-                           sizeof(priv->windowsize)) < 0) {
e3c68b
+                           sizeof(priv->windowsize)) != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR,
e3c68b
                        "setting receive window size "
e3c68b
                        "failed: %d: %d: %s",
e3c68b
@@ -3731,7 +3738,7 @@ socket_listen(rpc_transport_t *this)
e3c68b
             }
e3c68b
 
e3c68b
             if (setsockopt(priv->sock, SOL_SOCKET, SO_SNDBUF, &priv->windowsize,
e3c68b
-                           sizeof(priv->windowsize)) < 0) {
e3c68b
+                           sizeof(priv->windowsize)) != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR,
e3c68b
                        "setting send window size failed:"
e3c68b
                        " %d: %d: %s",
e3c68b
@@ -3741,7 +3748,7 @@ socket_listen(rpc_transport_t *this)
e3c68b
 
e3c68b
         if (priv->nodelay && (sa_family != AF_UNIX)) {
e3c68b
             ret = __socket_nodelay(priv->sock);
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR,
e3c68b
                        "setsockopt() failed for NODELAY (%s)", strerror(errno));
e3c68b
             }
e3c68b
@@ -3750,7 +3757,7 @@ socket_listen(rpc_transport_t *this)
e3c68b
         if (!priv->bio) {
e3c68b
             ret = __socket_nonblock(priv->sock);
e3c68b
 
e3c68b
-            if (ret == -1) {
e3c68b
+            if (ret != 0) {
e3c68b
                 gf_log(this->name, GF_LOG_ERROR,
e3c68b
                        "NBIO on socket %d failed "
e3c68b
                        "(errno:%s); closing socket",
e3c68b
@@ -3763,7 +3770,7 @@ socket_listen(rpc_transport_t *this)
e3c68b
 
e3c68b
         ret = __socket_server_bind(this);
e3c68b
 
e3c68b
-        if ((ret == -EADDRINUSE) || (ret == -1)) {
e3c68b
+        if (ret < 0) {
e3c68b
             /* logged inside __socket_server_bind() */
e3c68b
             gf_log(this->name, GF_LOG_ERROR,
e3c68b
                    "__socket_server_bind failed;"
e3c68b
@@ -3779,7 +3786,7 @@ socket_listen(rpc_transport_t *this)
e3c68b
 
e3c68b
         ret = listen(priv->sock, priv->backlog);
e3c68b
 
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret != 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR,
e3c68b
                    "could not set socket %d to listen mode (errno:%s); "
e3c68b
                    "closing socket",
e3c68b
@@ -4025,7 +4032,7 @@ reconfigure(rpc_transport_t *this, dict_t *options)
e3c68b
     priv = this->private;
e3c68b
 
e3c68b
     if (dict_get_str(options, "transport.socket.keepalive", &optstr) == 0) {
e3c68b
-        if (gf_string2boolean(optstr, &tmp_bool) == -1) {
e3c68b
+        if (gf_string2boolean(optstr, &tmp_bool) != 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR,
e3c68b
                    "'transport.socket.keepalive' takes only "
e3c68b
                    "boolean options, not taking any action");
e3c68b
@@ -4094,7 +4101,7 @@ reconfigure(rpc_transport_t *this, dict_t *options)
e3c68b
     if (dict_get(options, "non-blocking-io")) {
e3c68b
         optstr = data_to_str(dict_get(options, "non-blocking-io"));
e3c68b
 
e3c68b
-        if (gf_string2boolean(optstr, &tmp_bool) == -1) {
e3c68b
+        if (gf_string2boolean(optstr, &tmp_bool) != 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR,
e3c68b
                    "'non-blocking-io' takes only boolean options,"
e3c68b
                    " not taking any action");
e3c68b
@@ -4109,7 +4116,7 @@ reconfigure(rpc_transport_t *this, dict_t *options)
e3c68b
 
e3c68b
     if (!priv->bio) {
e3c68b
         ret = __socket_nonblock(priv->sock);
e3c68b
-        if (ret == -1) {
e3c68b
+        if (ret != 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING, "NBIO on %d failed (%s)",
e3c68b
                    priv->sock, strerror(errno));
e3c68b
             goto out;
e3c68b
@@ -4508,7 +4515,7 @@ socket_init(rpc_transport_t *this)
e3c68b
     if (dict_get(this->options, "non-blocking-io")) {
e3c68b
         optstr = data_to_str(dict_get(this->options, "non-blocking-io"));
e3c68b
 
e3c68b
-        if (gf_string2boolean(optstr, &tmp_bool) == -1) {
e3c68b
+        if (gf_string2boolean(optstr, &tmp_bool) != 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR,
e3c68b
                    "'non-blocking-io' takes only boolean options,"
e3c68b
                    " not taking any action");
e3c68b
@@ -4528,7 +4535,7 @@ socket_init(rpc_transport_t *this)
e3c68b
         optstr = data_to_str(
e3c68b
             dict_get(this->options, "transport.socket.nodelay"));
e3c68b
 
e3c68b
-        if (gf_string2boolean(optstr, &tmp_bool) == -1) {
e3c68b
+        if (gf_string2boolean(optstr, &tmp_bool) != 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR,
e3c68b
                    "'transport.socket.nodelay' takes only "
e3c68b
                    "boolean options, not taking any action");
e3c68b
@@ -4559,7 +4566,7 @@ socket_init(rpc_transport_t *this)
e3c68b
     priv->keepalivecnt = GF_KEEPALIVE_COUNT;
e3c68b
     if (dict_get_str(this->options, "transport.socket.keepalive", &optstr) ==
e3c68b
         0) {
e3c68b
-        if (gf_string2boolean(optstr, &tmp_bool) == -1) {
e3c68b
+        if (gf_string2boolean(optstr, &tmp_bool) != 0) {
e3c68b
             gf_log(this->name, GF_LOG_ERROR,
e3c68b
                    "'transport.socket.keepalive' takes only "
e3c68b
                    "boolean options, not taking any action");
e3c68b
@@ -4609,7 +4616,7 @@ socket_init(rpc_transport_t *this)
e3c68b
     if (dict_get(this->options, "transport.socket.read-fail-log")) {
e3c68b
         optstr = data_to_str(
e3c68b
             dict_get(this->options, "transport.socket.read-fail-log"));
e3c68b
-        if (gf_string2boolean(optstr, &tmp_bool) == -1) {
e3c68b
+        if (gf_string2boolean(optstr, &tmp_bool) != 0) {
e3c68b
             gf_log(this->name, GF_LOG_WARNING,
e3c68b
                    "'transport.socket.read-fail-log' takes only "
e3c68b
                    "boolean options; logging socket read fails");
e3c68b
@@ -4646,7 +4653,7 @@ fini(rpc_transport_t *this)
e3c68b
 
e3c68b
     priv = this->private;
e3c68b
     if (priv) {
e3c68b
-        if (priv->sock != -1) {
e3c68b
+        if (priv->sock >= 0) {
e3c68b
             pthread_mutex_lock(&priv->out_lock);
e3c68b
             {
e3c68b
                 __socket_ioq_flush(this);
e3c68b
@@ -4683,7 +4690,7 @@ init(rpc_transport_t *this)
e3c68b
 
e3c68b
     ret = socket_init(this);
e3c68b
 
e3c68b
-    if (ret == -1) {
e3c68b
+    if (ret < 0) {
e3c68b
         gf_log(this->name, GF_LOG_DEBUG, "socket_init() failed");
e3c68b
     }
e3c68b
 
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b