diff options
author | Krishnan Parthasarathi <kparthas@redhat.com> | 2015-02-25 15:49:11 +0530 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2015-02-27 21:16:11 -0800 |
commit | b117d4d84becd25ef79c049ebf9b8ec6c4abca88 (patch) | |
tree | 3e989a4fc35b10a6179d63032960be9bfe10d657 | |
parent | a0f30e637e6ee32b113fd21268be17e0618d39df (diff) |
socket: allow only one epoll thread to read msg fragments
__socket_read_reply function releases sock priv->lock briefly for
notifying higher layers of message's xid. This could result in other
epoll threads that are processing events on this socket to read further
fragments of the same message. This may lead to incorrect fragment
processing and result in a crash.
Change-Id: I915665b2e54ca16f2ad65970e51bf76c65d954a4
BUG: 1197118
Signed-off-by: Krishnan Parthasarathi <kparthas@redhat.com>
Signed-off-by: Shyam <srangana@redhat.com>
Reviewed-on: http://review.gluster.org/9742
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Tested-by: Raghavendra G <rgowdapp@redhat.com>
-rw-r--r-- | libglusterfs/src/event-epoll.c | 8 | ||||
-rw-r--r-- | rpc/rpc-transport/socket/src/socket.c | 12 | ||||
-rw-r--r-- | rpc/rpc-transport/socket/src/socket.h | 1 |
3 files changed, 18 insertions, 3 deletions
diff --git a/libglusterfs/src/event-epoll.c b/libglusterfs/src/event-epoll.c index 8d42fa71fb6..a8e9a08b93d 100644 --- a/libglusterfs/src/event-epoll.c +++ b/libglusterfs/src/event-epoll.c @@ -573,9 +573,11 @@ pre_unlock: thread calling event_select_on_epoll() while this thread was busy in handler() */ - event->events = slot->events; - ret = epoll_ctl (event_pool->fd, EPOLL_CTL_MOD, - fd, event); + if (slot->in_handler == 0) { + event->events = slot->events; + ret = epoll_ctl (event_pool->fd, EPOLL_CTL_MOD, + fd, event); + } } post_unlock: UNLOCK (&slot->lock); diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index 0a3a5812a91..a7e2bb0cfdf 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -1904,6 +1904,7 @@ __socket_read_reply (rpc_transport_t *this) /* release priv->lock, so as to avoid deadlock b/w conn->lock * and priv->lock, since we are doing an upcall here. */ + frag->state = SP_STATE_NOTIFYING_XID; pthread_mutex_unlock (&priv->lock); { ret = rpc_transport_notify (this, @@ -1912,6 +1913,9 @@ __socket_read_reply (rpc_transport_t *this) } pthread_mutex_lock (&priv->lock); + /* Transition back to externally visible state. */ + frag->state = SP_STATE_READ_MSGTYPE; + if (ret == -1) { gf_log (this->name, GF_LOG_WARNING, "notify for event MAP_XID failed for %s", @@ -1999,6 +2003,14 @@ __socket_read_frag (rpc_transport_t *this) } break; + + case SP_STATE_NOTIFYING_XID: + /* Another epoll thread is notifying higher layers + *of reply's xid. */ + errno = EAGAIN; + return -1; + break; + } out: diff --git a/rpc/rpc-transport/socket/src/socket.h b/rpc/rpc-transport/socket/src/socket.h index 33c936938eb..6a8ab870ab7 100644 --- a/rpc/rpc-transport/socket/src/socket.h +++ b/rpc/rpc-transport/socket/src/socket.h @@ -59,6 +59,7 @@ typedef enum { SP_STATE_RPCFRAG_INIT, SP_STATE_READING_MSGTYPE, SP_STATE_READ_MSGTYPE, + SP_STATE_NOTIFYING_XID } sp_rpcfrag_state_t; typedef enum { |