]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: ignore msg without session attached 8130/head
authorKefu Chai <kchai@redhat.com>
Tue, 15 Mar 2016 12:07:11 +0000 (20:07 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 17 Mar 2016 16:09:07 +0000 (00:09 +0800)
there is chance that a connection gets reset, and the session attached
to a message that was sent over this connection is reset. i.e.
con->set_priv(NULL) in Monitor::ms_handle_reset(), but we are about to
handle_command() this message after the message is somehow requeued. so,
not all MonOpRequests have an attached Session, especially those are
re-dispatched. we could check conn->is_connected() everywhere, but
that's error-prone and hard to maintain. so, in this change:

* we need to check for the session before looking at it closer.
* hold a reference to it when holding it, because in another thread,
  ms_handle_reset() could be freeing it.

Fixes: #15113
Signed-off-by: Kefu Chai <kchai@redhat.com>
src/mon/Monitor.cc

index ceea9f1ce1b70ee03ab8939e97869082eadffcd7..84e015fc53df1c6fdf708ff89ce7773945c62585 100644 (file)
@@ -18,6 +18,7 @@
 #include <signal.h>
 #include <limits.h>
 #include <cstring>
+#include <boost/scope_exit.hpp>
 
 #include "Monitor.h"
 #include "common/version.h"
@@ -2597,8 +2598,15 @@ void Monitor::handle_command(MonOpRequestRef op)
     return;
   }
 
-  MonSession *session = m->get_session();
-  assert(session);
+  MonSession *session = static_cast<MonSession *>(
+    m->get_connection()->get_priv());
+  if (!session) {
+    dout(5) << __func__ << " dropping stray message " << *m << dendl;
+    return;
+  }
+  BOOST_SCOPE_EXIT_ALL(=) {
+    session->put();
+  };
 
   if (m->cmd.empty()) {
     string rs = "No command supplied";