THRIFT-1522: Fixes Memory leak by wrapping getaddrinfo into a class.
Client: C++
Patch: Claudius Heine
Sponsored-by: Roger Meier <r.meier@siemens.com>
Signed-off-by: Claudius Heine <ch@denx.de>
This closes #542
diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp
index 0c973ee..215cda6 100644
--- a/lib/cpp/src/thrift/transport/TServerSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp
@@ -75,6 +75,42 @@
delete ssock;
}
+class TGetAddrInfoWrapper {
+public:
+ TGetAddrInfoWrapper(const char* node, const char* service, const struct addrinfo* hints);
+
+ virtual ~TGetAddrInfoWrapper();
+
+ int init();
+ const struct addrinfo* res();
+
+private:
+ const char* node_;
+ const char* service_;
+ const struct addrinfo* hints_;
+ struct addrinfo* res_;
+};
+
+TGetAddrInfoWrapper::TGetAddrInfoWrapper(const char* node,
+ const char* service,
+ const struct addrinfo* hints)
+ : node_(node), service_(service), hints_(hints), res_(NULL) {}
+
+TGetAddrInfoWrapper::~TGetAddrInfoWrapper() {
+ if (this->res_ != NULL)
+ freeaddrinfo(this->res_);
+}
+
+int TGetAddrInfoWrapper::init() {
+ if (this->res_ == NULL)
+ return getaddrinfo(this->node_, this->service_, this->hints_, &(this->res_));
+ return 0;
+}
+
+const struct addrinfo* TGetAddrInfoWrapper::res() {
+ return this->res_;
+}
+
namespace apache {
namespace thrift {
namespace transport {
@@ -236,7 +272,8 @@
throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid");
}
- struct addrinfo hints, *res, *res0;
+ struct addrinfo hints;
+ const struct addrinfo *res;
int error;
char port[sizeof("65535")];
std::memset(&hints, 0, sizeof(hints));
@@ -246,7 +283,9 @@
sprintf(port, "%d", port_);
// If address is not specified use wildcard address (NULL)
- error = getaddrinfo(address_.empty() ? NULL : &address_[0], port, &hints, &res0);
+ TGetAddrInfoWrapper info(address_.empty() ? NULL : &address_[0], port, &hints);
+
+ error = info.init();
if (error) {
GlobalOutput.printf("getaddrinfo %d: %s", error, THRIFT_GAI_STRERROR(error));
close();
@@ -256,7 +295,7 @@
// Pick the ipv6 address first since ipv4 addresses can be mapped
// into ipv6 space.
- for (res = res0; res; res = res->ai_next) {
+ for (res = info.res(); res; res = res->ai_next) {
if (res->ai_family == AF_INET6 || res->ai_next == NULL)
break;
}
@@ -453,9 +492,6 @@
// use short circuit evaluation here to only sleep if we need to
} while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0));
- // free addrinfo
- freeaddrinfo(res0);
-
// retrieve bind info
if (port_ == 0 && retries <= retryLimit_) {
struct sockaddr sa;