THRIFT-1522: Fixes Memory leak by wrapping getaddrinfo into a class. Client: C++ Patch: Claudius Heine
Sponsored-by: Roger Meier <[email protected]> Signed-off-by: Claudius Heine <[email protected]> This closes #542 Project: http://git-wip-us.apache.org/repos/asf/thrift/repo Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/d8ddb775 Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/d8ddb775 Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/d8ddb775 Branch: refs/heads/master Commit: d8ddb775e4330050e04cefa711f60250905978d3 Parents: 11c3569 Author: Claudius Heine <[email protected]> Authored: Mon Jul 6 09:14:25 2015 +0200 Committer: Nobuaki Sukegawa <[email protected]> Committed: Mon Nov 9 00:02:18 2015 +0900 ---------------------------------------------------------------------- lib/cpp/src/thrift/transport/TServerSocket.cpp | 48 ++++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/thrift/blob/d8ddb775/lib/cpp/src/thrift/transport/TServerSocket.cpp ---------------------------------------------------------------------- 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 @@ void destroyer_of_fine_sockets(THRIFT_SOCKET* ssock) { 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 @@ void TServerSocket::listen() { 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 @@ void TServerSocket::listen() { 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 @@ void TServerSocket::listen() { // 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 @@ void TServerSocket::listen() { // 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;
