Skip to content

Commit

Permalink
THRIFT-1522: Fixes Memory leak by wrapping getaddrinfo into a class.
Browse files Browse the repository at this point in the history
Client: C++
Patch: Claudius Heine

Sponsored-by: Roger Meier <[email protected]>
Signed-off-by: Claudius Heine <[email protected]>

This closes #542
  • Loading branch information
cmhe authored and nsuke committed Nov 8, 2015
1 parent 11c3569 commit d8ddb77
Showing 1 changed file with 42 additions and 6 deletions.
48 changes: 42 additions & 6 deletions lib/cpp/src/thrift/transport/TServerSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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));
Expand All @@ -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();
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit d8ddb77

Please sign in to comment.