]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librados: fix resources leakage in RadosClient::connect().
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Mon, 19 Jan 2015 14:07:21 +0000 (15:07 +0100)
committerLoic Dachary <ldachary@redhat.com>
Fri, 27 Feb 2015 18:14:44 +0000 (19:14 +0100)
If RadosClient::connect was called a second time (which could
happen as a part of recovery from failure), the instances
of Objecter and Messenger allocated by the first call were leaked.

Additionally, the implementation of the method wrongly reported
memory allocation problems -- it throwed std::bad_alloc exception
instead of returning -ENOMEM error code.

Fixes: #10425
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
(cherry picked from commit 624c056da093c8741242892413438a291c03c7d5)

Conflicts:
src/librados/RadosClient.cc
        resolve adding (std::nothrow) that failed because the
        prototype of the constructor is not the same

src/librados/RadosClient.cc
src/test/librados/misc.cc

index 9330e65368048407d728ca50e39e2bd6d4a8b111..09bc507420ec0a783dd84e8d9787e7260ca21075 100644 (file)
@@ -236,7 +236,7 @@ int librados::RadosClient::connect()
   ldout(cct, 1) << "starting objecter" << dendl;
 
   err = -ENOMEM;
-  objecter = new Objecter(cct, messenger, &monclient, &osdmap, lock, timer,
+  objecter = new (std::nothrow) Objecter(cct, messenger, &monclient, &osdmap, lock, timer,
                          cct->_conf->rados_mon_op_timeout,
                          cct->_conf->rados_osd_op_timeout);
   if (!objecter)
@@ -287,8 +287,19 @@ int librados::RadosClient::connect()
   err = 0;
 
  out:
-  if (err)
+  if (err) {
     state = DISCONNECTED;
+
+    if (objecter) {
+      delete objecter;
+      objecter = NULL;
+    }
+    if (messenger) {
+      delete messenger;
+      messenger = NULL;
+    }
+  }
+
   return err;
 }
 
index 38443ce114665e9756b629575f5d9dfb3db9ff12..259942a4ba7fd275c884d9c1804ad598df775f98 100644 (file)
@@ -39,6 +39,25 @@ TEST(LibRadosMiscVersion, VersionPP) {
   Rados::version(&major, &minor, &extra);
 }
 
+TEST(LibRadosMiscConnectFailure, ConnectFailure) {
+  rados_t cluster;
+
+  char *id = getenv("CEPH_CLIENT_ID");
+  if (id)
+    std::cerr << "Client id is: " << id << std::endl;
+
+  ASSERT_EQ(0, rados_create(&cluster, NULL));
+  ASSERT_EQ(0, rados_conf_read_file(cluster, NULL));
+  ASSERT_EQ(0, rados_conf_parse_env(cluster, NULL));
+
+  ASSERT_EQ(0, rados_conf_set(cluster, "client_mount_timeout", "0.000001"));
+
+  ASSERT_NE(0, rados_connect(cluster));
+  ASSERT_NE(0, rados_connect(cluster));
+
+  rados_shutdown(cluster);
+}
+
 TEST_F(LibRadosMisc, ClusterFSID) {
   char fsid[37];
   ASSERT_EQ(-ERANGE, rados_cluster_fsid(cluster, fsid, sizeof(fsid) - 1));