|
|
21ab4e |
From 893f1428fb7153ea504ba7e85b729be05cb185b8 Mon Sep 17 00:00:00 2001
|
|
|
21ab4e |
From: Milind Changire <mchangir@redhat.com>
|
|
|
21ab4e |
Date: Tue, 9 May 2017 17:51:18 +0530
|
|
|
21ab4e |
Subject: [PATCH 424/426] rpc: fix transport add/remove race on port probing
|
|
|
21ab4e |
|
|
|
21ab4e |
Problem:
|
|
|
21ab4e |
Spurious __gf_free() assertion failures seen all over the place with
|
|
|
21ab4e |
header->magic being overwritten when running port probing tests with
|
|
|
21ab4e |
'nmap'
|
|
|
21ab4e |
|
|
|
21ab4e |
Solution:
|
|
|
21ab4e |
Fix sequence of:
|
|
|
21ab4e |
1. add accept()ed socket connection fd to epoll set
|
|
|
21ab4e |
2. add newly created rpc_transport_t object in RPCSVC service list
|
|
|
21ab4e |
|
|
|
21ab4e |
Correct sequence is #2 followed by #1.
|
|
|
21ab4e |
|
|
|
21ab4e |
Reason:
|
|
|
21ab4e |
Adding new fd returned by accept() to epoll set causes an epoll_wait()
|
|
|
21ab4e |
to return immediately with a POLLIN event. This races ahead to a readv()
|
|
|
21ab4e |
which returms with errno:104 (Connection reset by peer) during port
|
|
|
21ab4e |
probing using 'nmap'. The error is then handled by POLLERR code to
|
|
|
21ab4e |
remove the new transport object from RPCSVC service list and later
|
|
|
21ab4e |
unref and destroy the rpc transport object.
|
|
|
21ab4e |
socket_server_event_handler() then catches up with registering the
|
|
|
21ab4e |
unref'd/destroyed rpc transport object. This is later manifest as
|
|
|
21ab4e |
assertion failures in __gf_free() with the header->magic field botched
|
|
|
21ab4e |
due to invalid address references.
|
|
|
21ab4e |
All this does not result in a Segmentation Fault since the address
|
|
|
21ab4e |
space continues to be mapped into the process and pages still being
|
|
|
21ab4e |
referenced elsewhere.
|
|
|
21ab4e |
|
|
|
21ab4e |
As a further note:
|
|
|
21ab4e |
This race happens only in accept() codepath. Only in this codepath,
|
|
|
21ab4e |
the notify will be referring to two transports:
|
|
|
21ab4e |
1, listener transport and
|
|
|
21ab4e |
2. newly accepted transport
|
|
|
21ab4e |
All other notify refer to only one transport i.e., the transport/socket
|
|
|
21ab4e |
on which the event is received. Since epoll is ONE_SHOT another event
|
|
|
21ab4e |
won't arrive on the same socket till the current event is processed.
|
|
|
21ab4e |
However, in the accept() codepath, the current event - ACCEPT - and the
|
|
|
21ab4e |
new event - POLLIN/POLLER - arrive on two different sockets:
|
|
|
21ab4e |
1. ACCEPT on listener socket and
|
|
|
21ab4e |
2. POLLIN/POLLERR on newly registered socket.
|
|
|
21ab4e |
Also, note that these two events are handled different thread contexts.
|
|
|
21ab4e |
|
|
|
21ab4e |
Cleanup:
|
|
|
21ab4e |
Critical section in socket_server_event_handler() has been removed.
|
|
|
21ab4e |
Instead, an additional ref on new_trans has been used to avoid ref/unref
|
|
|
21ab4e |
race when notifying RPCSVC.
|
|
|
21ab4e |
|
|
|
21ab4e |
mainline:
|
|
|
21ab4e |
> BUG: 1438966
|
|
|
21ab4e |
> Signed-off-by: Milind Changire <mchangir@redhat.com>
|
|
|
21ab4e |
> Reviewed-on: https://review.gluster.org/17139
|
|
|
21ab4e |
> Smoke: Gluster Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
|
|
|
21ab4e |
> Reviewed-by: Amar Tumballi <amarts@redhat.com>
|
|
|
21ab4e |
> Reviewed-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
|
|
21ab4e |
> Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
|
|
|
21ab4e |
(cherry picked from commit 4f7ef3020edcc75cdeb22d8da8a1484f9db77ac9)
|
|
|
21ab4e |
|
|
|
21ab4e |
Change-Id: I4417924bc9e6277d24bd1a1c5bcb7445bcb226a3
|
|
|
21ab4e |
BUG: 1442535
|
|
|
21ab4e |
Signed-off-by: Milind Changire <mchangir@redhat.com>
|
|
|
21ab4e |
Reviewed-on: https://code.engineering.redhat.com/gerrit/105653
|
|
|
21ab4e |
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
|
|
|
21ab4e |
---
|
|
|
21ab4e |
rpc/rpc-transport/socket/src/socket.c | 359 ++++++++++++++++++----------------
|
|
|
21ab4e |
1 file changed, 195 insertions(+), 164 deletions(-)
|
|
|
21ab4e |
|
|
|
21ab4e |
diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c
|
|
|
21ab4e |
index ca939bb..f64e2f0 100644
|
|
|
21ab4e |
--- a/rpc/rpc-transport/socket/src/socket.c
|
|
|
21ab4e |
+++ b/rpc/rpc-transport/socket/src/socket.c
|
|
|
21ab4e |
@@ -2671,107 +2671,106 @@ socket_server_event_handler (int fd, int idx, void *data,
|
|
|
21ab4e |
priv = this->private;
|
|
|
21ab4e |
ctx = this->ctx;
|
|
|
21ab4e |
|
|
|
21ab4e |
- pthread_mutex_lock (&priv->lock);
|
|
|
21ab4e |
- {
|
|
|
21ab4e |
- priv->idx = idx;
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- if (poll_in) {
|
|
|
21ab4e |
- new_sock = accept (priv->sock, SA (&new_sockaddr),
|
|
|
21ab4e |
- &addrlen);
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- if (new_sock == -1) {
|
|
|
21ab4e |
- gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
- "accept on %d failed (%s)",
|
|
|
21ab4e |
- priv->sock, strerror (errno));
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- if (priv->nodelay && (new_sockaddr.ss_family != AF_UNIX)) {
|
|
|
21ab4e |
- ret = __socket_nodelay (new_sock);
|
|
|
21ab4e |
- if (ret == -1) {
|
|
|
21ab4e |
- gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
- "setsockopt() failed for "
|
|
|
21ab4e |
- "NODELAY (%s)",
|
|
|
21ab4e |
- strerror (errno));
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
+ /* NOTE:
|
|
|
21ab4e |
+ * We have done away with the critical section in this function. since
|
|
|
21ab4e |
+ * there's little that it helps with. There's no other code that
|
|
|
21ab4e |
+ * attempts to unref the listener socket/transport from any other
|
|
|
21ab4e |
+ * thread context while we are using it here.
|
|
|
21ab4e |
+ */
|
|
|
21ab4e |
+ priv->idx = idx;
|
|
|
21ab4e |
|
|
|
21ab4e |
- if (priv->keepalive &&
|
|
|
21ab4e |
- new_sockaddr.ss_family != AF_UNIX) {
|
|
|
21ab4e |
- ret = __socket_keepalive (new_sock,
|
|
|
21ab4e |
- new_sockaddr.ss_family,
|
|
|
21ab4e |
- priv->keepaliveintvl,
|
|
|
21ab4e |
- priv->keepaliveidle,
|
|
|
21ab4e |
- priv->timeout);
|
|
|
21ab4e |
- if (ret == -1)
|
|
|
21ab4e |
- gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
- "Failed to set keep-alive: %s",
|
|
|
21ab4e |
- strerror (errno));
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
+ if (poll_in) {
|
|
|
21ab4e |
+ new_sock = accept (priv->sock, SA (&new_sockaddr), &addrlen);
|
|
|
21ab4e |
|
|
|
21ab4e |
- new_trans = GF_CALLOC (1, sizeof (*new_trans),
|
|
|
21ab4e |
- gf_common_mt_rpc_trans_t);
|
|
|
21ab4e |
- if (!new_trans) {
|
|
|
21ab4e |
- sys_close (new_sock);
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
+ if (new_sock == -1) {
|
|
|
21ab4e |
+ gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
+ "accept on %d failed (%s)",
|
|
|
21ab4e |
+ priv->sock, strerror (errno));
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
|
|
|
21ab4e |
- ret = pthread_mutex_init(&new_trans->lock, NULL);
|
|
|
21ab4e |
+ if (priv->nodelay && (new_sockaddr.ss_family != AF_UNIX)) {
|
|
|
21ab4e |
+ ret = __socket_nodelay (new_sock);
|
|
|
21ab4e |
if (ret == -1) {
|
|
|
21ab4e |
gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
- "pthread_mutex_init() failed: %s",
|
|
|
21ab4e |
+ "setsockopt() failed for "
|
|
|
21ab4e |
+ "NODELAY (%s)",
|
|
|
21ab4e |
strerror (errno));
|
|
|
21ab4e |
- sys_close (new_sock);
|
|
|
21ab4e |
- GF_FREE (new_trans);
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
- INIT_LIST_HEAD (&new_trans->list);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
|
|
|
21ab4e |
- new_trans->name = gf_strdup (this->name);
|
|
|
21ab4e |
+ if (priv->keepalive &&
|
|
|
21ab4e |
+ new_sockaddr.ss_family != AF_UNIX) {
|
|
|
21ab4e |
+ ret = __socket_keepalive (new_sock,
|
|
|
21ab4e |
+ new_sockaddr.ss_family,
|
|
|
21ab4e |
+ priv->keepaliveintvl,
|
|
|
21ab4e |
+ priv->keepaliveidle,
|
|
|
21ab4e |
+ priv->timeout);
|
|
|
21ab4e |
+ if (ret == -1)
|
|
|
21ab4e |
+ gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
+ "Failed to set keep-alive: %s",
|
|
|
21ab4e |
+ strerror (errno));
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
|
|
|
21ab4e |
- memcpy (&new_trans->peerinfo.sockaddr, &new_sockaddr,
|
|
|
21ab4e |
- addrlen);
|
|
|
21ab4e |
- new_trans->peerinfo.sockaddr_len = addrlen;
|
|
|
21ab4e |
+ new_trans = GF_CALLOC (1, sizeof (*new_trans),
|
|
|
21ab4e |
+ gf_common_mt_rpc_trans_t);
|
|
|
21ab4e |
+ if (!new_trans) {
|
|
|
21ab4e |
+ sys_close (new_sock);
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
|
|
|
21ab4e |
- new_trans->myinfo.sockaddr_len =
|
|
|
21ab4e |
- sizeof (new_trans->myinfo.sockaddr);
|
|
|
21ab4e |
+ ret = pthread_mutex_init(&new_trans->lock, NULL);
|
|
|
21ab4e |
+ if (ret == -1) {
|
|
|
21ab4e |
+ gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
+ "pthread_mutex_init() failed: %s",
|
|
|
21ab4e |
+ strerror (errno));
|
|
|
21ab4e |
+ sys_close (new_sock);
|
|
|
21ab4e |
+ GF_FREE (new_trans);
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+ INIT_LIST_HEAD (&new_trans->list);
|
|
|
21ab4e |
|
|
|
21ab4e |
- ret = getsockname (new_sock,
|
|
|
21ab4e |
- SA (&new_trans->myinfo.sockaddr),
|
|
|
21ab4e |
- &new_trans->myinfo.sockaddr_len);
|
|
|
21ab4e |
- if (ret == -1) {
|
|
|
21ab4e |
- gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
- "getsockname on %d failed (%s)",
|
|
|
21ab4e |
- new_sock, strerror (errno));
|
|
|
21ab4e |
- sys_close (new_sock);
|
|
|
21ab4e |
- GF_FREE (new_trans->name);
|
|
|
21ab4e |
- GF_FREE (new_trans);
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
+ new_trans->name = gf_strdup (this->name);
|
|
|
21ab4e |
|
|
|
21ab4e |
- get_transport_identifiers (new_trans);
|
|
|
21ab4e |
- ret = socket_init(new_trans);
|
|
|
21ab4e |
- if (ret != 0) {
|
|
|
21ab4e |
- sys_close (new_sock);
|
|
|
21ab4e |
- GF_FREE (new_trans->name);
|
|
|
21ab4e |
- GF_FREE (new_trans);
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
- new_trans->ops = this->ops;
|
|
|
21ab4e |
- new_trans->init = this->init;
|
|
|
21ab4e |
- new_trans->fini = this->fini;
|
|
|
21ab4e |
- new_trans->ctx = ctx;
|
|
|
21ab4e |
- new_trans->xl = this->xl;
|
|
|
21ab4e |
- new_trans->mydata = this->mydata;
|
|
|
21ab4e |
- new_trans->notify = this->notify;
|
|
|
21ab4e |
- new_trans->listener = this;
|
|
|
21ab4e |
- new_priv = new_trans->private;
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- if (new_sockaddr.ss_family == AF_UNIX) {
|
|
|
21ab4e |
- new_priv->use_ssl = _gf_false;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
- else {
|
|
|
21ab4e |
- switch (priv->srvr_ssl) {
|
|
|
21ab4e |
+ memcpy (&new_trans->peerinfo.sockaddr, &new_sockaddr, addrlen);
|
|
|
21ab4e |
+ new_trans->peerinfo.sockaddr_len = addrlen;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ new_trans->myinfo.sockaddr_len = sizeof (new_trans->myinfo.sockaddr);
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ ret = getsockname (new_sock, SA (&new_trans->myinfo.sockaddr),
|
|
|
21ab4e |
+ &new_trans->myinfo.sockaddr_len);
|
|
|
21ab4e |
+ if (ret == -1) {
|
|
|
21ab4e |
+ gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
+ "getsockname on %d failed (%s)",
|
|
|
21ab4e |
+ new_sock, strerror (errno));
|
|
|
21ab4e |
+ sys_close (new_sock);
|
|
|
21ab4e |
+ GF_FREE (new_trans->name);
|
|
|
21ab4e |
+ GF_FREE (new_trans);
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ get_transport_identifiers (new_trans);
|
|
|
21ab4e |
+ ret = socket_init(new_trans);
|
|
|
21ab4e |
+ if (ret != 0) {
|
|
|
21ab4e |
+ sys_close (new_sock);
|
|
|
21ab4e |
+ GF_FREE (new_trans->name);
|
|
|
21ab4e |
+ GF_FREE (new_trans);
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+ new_trans->ops = this->ops;
|
|
|
21ab4e |
+ new_trans->init = this->init;
|
|
|
21ab4e |
+ new_trans->fini = this->fini;
|
|
|
21ab4e |
+ new_trans->ctx = ctx;
|
|
|
21ab4e |
+ new_trans->xl = this->xl;
|
|
|
21ab4e |
+ new_trans->mydata = this->mydata;
|
|
|
21ab4e |
+ new_trans->notify = this->notify;
|
|
|
21ab4e |
+ new_trans->listener = this;
|
|
|
21ab4e |
+ new_priv = new_trans->private;
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ if (new_sockaddr.ss_family == AF_UNIX) {
|
|
|
21ab4e |
+ new_priv->use_ssl = _gf_false;
|
|
|
21ab4e |
+ } else {
|
|
|
21ab4e |
+ switch (priv->srvr_ssl) {
|
|
|
21ab4e |
case MGMT_SSL_ALWAYS:
|
|
|
21ab4e |
/* Glusterd with secure_mgmt. */
|
|
|
21ab4e |
new_priv->use_ssl = _gf_true;
|
|
|
21ab4e |
@@ -2782,95 +2781,127 @@ socket_server_event_handler (int fd, int idx, void *data,
|
|
|
21ab4e |
break;
|
|
|
21ab4e |
default:
|
|
|
21ab4e |
new_priv->use_ssl = _gf_false;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
}
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
|
|
|
21ab4e |
- new_priv->sock = new_sock;
|
|
|
21ab4e |
- new_priv->own_thread = priv->own_thread;
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- new_priv->ssl_ctx = priv->ssl_ctx;
|
|
|
21ab4e |
- if (new_priv->use_ssl && !new_priv->own_thread) {
|
|
|
21ab4e |
- cname = ssl_setup_connection(new_trans,1);
|
|
|
21ab4e |
- if (!cname) {
|
|
|
21ab4e |
- gf_log(this->name,GF_LOG_ERROR,
|
|
|
21ab4e |
- "server setup failed");
|
|
|
21ab4e |
- sys_close (new_sock);
|
|
|
21ab4e |
- GF_FREE (new_trans->name);
|
|
|
21ab4e |
- GF_FREE (new_trans);
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
- this->ssl_name = cname;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
+ new_priv->sock = new_sock;
|
|
|
21ab4e |
+ new_priv->own_thread = priv->own_thread;
|
|
|
21ab4e |
|
|
|
21ab4e |
- if (!priv->bio && !priv->own_thread) {
|
|
|
21ab4e |
- ret = __socket_nonblock (new_sock);
|
|
|
21ab4e |
+ new_priv->ssl_ctx = priv->ssl_ctx;
|
|
|
21ab4e |
+ if (new_priv->use_ssl && !new_priv->own_thread) {
|
|
|
21ab4e |
+ cname = ssl_setup_connection(new_trans, 1);
|
|
|
21ab4e |
+ if (!cname) {
|
|
|
21ab4e |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
21ab4e |
+ "server setup failed");
|
|
|
21ab4e |
+ sys_close (new_sock);
|
|
|
21ab4e |
+ GF_FREE (new_trans->name);
|
|
|
21ab4e |
+ GF_FREE (new_trans);
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+ this->ssl_name = cname;
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
|
|
|
21ab4e |
- if (ret == -1) {
|
|
|
21ab4e |
- gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
- "NBIO on %d failed (%s)",
|
|
|
21ab4e |
- new_sock, strerror (errno));
|
|
|
21ab4e |
+ if (!priv->bio && !priv->own_thread) {
|
|
|
21ab4e |
+ ret = __socket_nonblock (new_sock);
|
|
|
21ab4e |
|
|
|
21ab4e |
- sys_close (new_sock);
|
|
|
21ab4e |
- GF_FREE (new_trans->name);
|
|
|
21ab4e |
- GF_FREE (new_trans);
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
+ if (ret == -1) {
|
|
|
21ab4e |
+ gf_log (this->name, GF_LOG_WARNING,
|
|
|
21ab4e |
+ "NBIO on %d failed (%s)",
|
|
|
21ab4e |
+ new_sock, strerror (errno));
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ sys_close (new_sock);
|
|
|
21ab4e |
+ GF_FREE (new_trans->name);
|
|
|
21ab4e |
+ GF_FREE (new_trans);
|
|
|
21ab4e |
+ goto out;
|
|
|
21ab4e |
}
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
|
|
|
21ab4e |
- pthread_mutex_lock (&new_priv->lock);
|
|
|
21ab4e |
- {
|
|
|
21ab4e |
- /*
|
|
|
21ab4e |
- * In the own_thread case, this is used to
|
|
|
21ab4e |
- * indicate that we're initializing a server
|
|
|
21ab4e |
- * connection.
|
|
|
21ab4e |
- */
|
|
|
21ab4e |
- new_priv->connected = 1;
|
|
|
21ab4e |
- new_priv->is_server = _gf_true;
|
|
|
21ab4e |
- rpc_transport_ref (new_trans);
|
|
|
21ab4e |
-
|
|
|
21ab4e |
- if (new_priv->own_thread) {
|
|
|
21ab4e |
- if (pipe(new_priv->pipe) < 0) {
|
|
|
21ab4e |
- gf_log(this->name, GF_LOG_ERROR,
|
|
|
21ab4e |
- "could not create pipe");
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
- ret = socket_spawn(new_trans);
|
|
|
21ab4e |
- if (ret) {
|
|
|
21ab4e |
- gf_log(this->name, GF_LOG_ERROR,
|
|
|
21ab4e |
- "could not spawn thread");
|
|
|
21ab4e |
- sys_close (new_priv->pipe[0]);
|
|
|
21ab4e |
- sys_close (new_priv->pipe[1]);
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
- } else {
|
|
|
21ab4e |
- new_priv->idx =
|
|
|
21ab4e |
- event_register (ctx->event_pool,
|
|
|
21ab4e |
- new_sock,
|
|
|
21ab4e |
- socket_event_handler,
|
|
|
21ab4e |
- new_trans,
|
|
|
21ab4e |
- 1, 0);
|
|
|
21ab4e |
- if (new_priv->idx == -1) {
|
|
|
21ab4e |
- ret = -1;
|
|
|
21ab4e |
- gf_log(this->name, GF_LOG_ERROR,
|
|
|
21ab4e |
- "failed to register the socket with event");
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
+ /*
|
|
|
21ab4e |
+ * In the own_thread case, this is used to
|
|
|
21ab4e |
+ * indicate that we're initializing a server
|
|
|
21ab4e |
+ * connection.
|
|
|
21ab4e |
+ */
|
|
|
21ab4e |
+ new_priv->connected = 1;
|
|
|
21ab4e |
+ new_priv->is_server = _gf_true;
|
|
|
21ab4e |
+ rpc_transport_ref (new_trans);
|
|
|
21ab4e |
|
|
|
21ab4e |
+ if (new_priv->own_thread) {
|
|
|
21ab4e |
+ if (pipe(new_priv->pipe) < 0) {
|
|
|
21ab4e |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
21ab4e |
+ "could not create pipe");
|
|
|
21ab4e |
}
|
|
|
21ab4e |
- pthread_mutex_unlock (&new_priv->lock);
|
|
|
21ab4e |
- if (ret == -1) {
|
|
|
21ab4e |
- sys_close (new_sock);
|
|
|
21ab4e |
- rpc_transport_unref (new_trans);
|
|
|
21ab4e |
- goto unlock;
|
|
|
21ab4e |
+ ret = socket_spawn(new_trans);
|
|
|
21ab4e |
+ if (ret) {
|
|
|
21ab4e |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
21ab4e |
+ "could not spawn thread");
|
|
|
21ab4e |
+ sys_close (new_priv->pipe[0]);
|
|
|
21ab4e |
+ sys_close (new_priv->pipe[1]);
|
|
|
21ab4e |
}
|
|
|
21ab4e |
+ } else {
|
|
|
21ab4e |
+ /* Take a ref on the new_trans to avoid
|
|
|
21ab4e |
+ * getting deleted when event_register()
|
|
|
21ab4e |
+ * causes socket_event_handler() to race
|
|
|
21ab4e |
+ * ahead of this path to eventually find
|
|
|
21ab4e |
+ * a disconnect and unref the transport
|
|
|
21ab4e |
+ */
|
|
|
21ab4e |
+ rpc_transport_ref (new_trans);
|
|
|
21ab4e |
|
|
|
21ab4e |
- if (!priv->own_thread) {
|
|
|
21ab4e |
- ret = rpc_transport_notify (this,
|
|
|
21ab4e |
- RPC_TRANSPORT_ACCEPT, new_trans);
|
|
|
21ab4e |
+ /* Send a notification to RPCSVC layer
|
|
|
21ab4e |
+ * to save the new_trans in its service
|
|
|
21ab4e |
+ * list before we register the new_sock
|
|
|
21ab4e |
+ * with epoll to begin receiving notifications
|
|
|
21ab4e |
+ * for data handling.
|
|
|
21ab4e |
+ */
|
|
|
21ab4e |
+ ret = rpc_transport_notify (this, RPC_TRANSPORT_ACCEPT, new_trans);
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ if (ret != -1) {
|
|
|
21ab4e |
+ new_priv->idx =
|
|
|
21ab4e |
+ event_register (ctx->event_pool,
|
|
|
21ab4e |
+ new_sock,
|
|
|
21ab4e |
+ socket_event_handler,
|
|
|
21ab4e |
+ new_trans,
|
|
|
21ab4e |
+ 1, 0);
|
|
|
21ab4e |
+ if (new_priv->idx == -1) {
|
|
|
21ab4e |
+ ret = -1;
|
|
|
21ab4e |
+ gf_log(this->name, GF_LOG_ERROR,
|
|
|
21ab4e |
+ "failed to register the socket "
|
|
|
21ab4e |
+ "with event");
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ /* event_register() could have failed for some
|
|
|
21ab4e |
+ * reason, implying that the new_sock cannot be
|
|
|
21ab4e |
+ * added to the epoll set. If we wont get any
|
|
|
21ab4e |
+ * more notifications for new_sock from epoll,
|
|
|
21ab4e |
+ * then we better remove the corresponding
|
|
|
21ab4e |
+ * new_trans object from the RPCSVC service list.
|
|
|
21ab4e |
+ * Since we've notified RPC service of new_trans
|
|
|
21ab4e |
+ * before we attempted event_register(), we better
|
|
|
21ab4e |
+ * unlink the new_trans from the RPCSVC service list
|
|
|
21ab4e |
+ * to cleanup the stateby sending out a DISCONNECT
|
|
|
21ab4e |
+ * notification.
|
|
|
21ab4e |
+ */
|
|
|
21ab4e |
+ rpc_transport_notify (this, RPC_TRANSPORT_DISCONNECT, new_trans);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
}
|
|
|
21ab4e |
+
|
|
|
21ab4e |
+ /* this rpc_transport_unref() is for managing race between
|
|
|
21ab4e |
+ * 1. socket_server_event_handler and
|
|
|
21ab4e |
+ * 2. socket_event_handler
|
|
|
21ab4e |
+ * trying to add and remove new_trans from the rpcsvc
|
|
|
21ab4e |
+ * service list
|
|
|
21ab4e |
+ * now that we are done with the notifications, lets
|
|
|
21ab4e |
+ * reduce the reference
|
|
|
21ab4e |
+ */
|
|
|
21ab4e |
+ rpc_transport_unref (new_trans);
|
|
|
21ab4e |
}
|
|
|
21ab4e |
- }
|
|
|
21ab4e |
-unlock:
|
|
|
21ab4e |
- pthread_mutex_unlock (&priv->lock);
|
|
|
21ab4e |
|
|
|
21ab4e |
+ if (ret == -1) {
|
|
|
21ab4e |
+ sys_close (new_sock);
|
|
|
21ab4e |
+ /* this unref is to actually cause the destruction of
|
|
|
21ab4e |
+ * the new_trans since we've failed at everything so far
|
|
|
21ab4e |
+ */
|
|
|
21ab4e |
+ rpc_transport_unref (new_trans);
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
+ }
|
|
|
21ab4e |
out:
|
|
|
21ab4e |
if (cname && (cname != this->ssl_name)) {
|
|
|
21ab4e |
GF_FREE(cname);
|
|
|
21ab4e |
--
|
|
|
21ab4e |
1.8.3.1
|
|
|
21ab4e |
|