From 1b2667211f90a1b630d2ddffe99b0fb00bb3c07c Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Mon, 19 Jan 2015 15:07:21 +0100 Subject: [PATCH] librados: fix resources leakage in RadosClient::connect(). 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 (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 | 15 +++++++++++++-- src/test/librados/misc.cc | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/librados/RadosClient.cc b/src/librados/RadosClient.cc index 9330e65368048..09bc507420ec0 100644 --- a/src/librados/RadosClient.cc +++ b/src/librados/RadosClient.cc @@ -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; } diff --git a/src/test/librados/misc.cc b/src/test/librados/misc.cc index 38443ce114665..259942a4ba7fd 100644 --- a/src/test/librados/misc.cc +++ b/src/test/librados/misc.cc @@ -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)); -- 2.39.5