Commit cae6c97a authored by Soren Lassen's avatar Soren Lassen Committed by Anton Likhtarov

Fix folly memory leaks found with clang:dev + asan.

Summary: I tried running folly/test with clang:dev and asan and found these leaks.

Test Plan:
unit tests with clang:dev/asan

Reviewed By: davejwatson@fb.com

Subscribers: davejwatson, trunkagent, mathieubaudet, njormrod, meyering, philipp

FB internal diff: D1569246
parent 395c7e78
...@@ -201,12 +201,11 @@ void SocketAddress::setFromLocalAddress(int socket) { ...@@ -201,12 +201,11 @@ void SocketAddress::setFromLocalAddress(int socket) {
} }
void SocketAddress::setFromSockaddr(const struct sockaddr* address) { void SocketAddress::setFromSockaddr(const struct sockaddr* address) {
uint16_t port;
if (address->sa_family == AF_INET) { if (address->sa_family == AF_INET) {
storage_.addr = folly::IPAddress(address); port = ntohs(((sockaddr_in*)address)->sin_port);
port_ = ntohs(((sockaddr_in*)address)->sin_port);
} else if (address->sa_family == AF_INET6) { } else if (address->sa_family == AF_INET6) {
storage_.addr = folly::IPAddress(address); port = ntohs(((sockaddr_in6*)address)->sin6_port);
port_ = ntohs(((sockaddr_in6*)address)->sin6_port);
} else if (address->sa_family == AF_UNIX) { } else if (address->sa_family == AF_UNIX) {
// We need an explicitly specified length for AF_UNIX addresses, // We need an explicitly specified length for AF_UNIX addresses,
// to be able to distinguish anonymous addresses from addresses // to be able to distinguish anonymous addresses from addresses
...@@ -220,7 +219,12 @@ void SocketAddress::setFromSockaddr(const struct sockaddr* address) { ...@@ -220,7 +219,12 @@ void SocketAddress::setFromSockaddr(const struct sockaddr* address) {
"SocketAddress::setFromSockaddr() called " "SocketAddress::setFromSockaddr() called "
"with unsupported address type"); "with unsupported address type");
} }
external_ = false; if (getFamily() == AF_UNIX) {
storage_.un.free();
external_ = false;
}
storage_.addr = folly::IPAddress(address);
port_ = port;
} }
void SocketAddress::setFromSockaddr(const struct sockaddr* address, void SocketAddress::setFromSockaddr(const struct sockaddr* address,
......
...@@ -391,13 +391,16 @@ public: ...@@ -391,13 +391,16 @@ public:
try { try {
std::uninitialized_copy(o.begin(), o.end(), begin()); std::uninitialized_copy(o.begin(), o.end(), begin());
} catch (...) { } catch (...) {
if (this->isExtern()) u.freeHeap(); if (this->isExtern()) {
u.freeHeap();
}
throw; throw;
} }
this->setSize(n); this->setSize(n);
} }
small_vector(small_vector&& o) { small_vector(small_vector&& o)
noexcept(std::is_nothrow_move_constructible<Value>::value) {
if (o.isExtern()) { if (o.isExtern()) {
swap(o); swap(o);
} else { } else {
...@@ -877,18 +880,31 @@ private: ...@@ -877,18 +880,31 @@ private:
auto distance = std::distance(first, last); auto distance = std::distance(first, last);
makeSize(distance); makeSize(distance);
this->setSize(distance); this->setSize(distance);
try {
detail::populateMemForward(data(), distance, detail::populateMemForward(data(), distance,
[&] (void* p) { new (p) value_type(*first++); } [&] (void* p) { new (p) value_type(*first++); }
); );
} catch (...) {
if (this->isExtern()) {
u.freeHeap();
}
throw;
}
} }
void doConstruct(size_type n, value_type const& val) { void doConstruct(size_type n, value_type const& val) {
makeSize(n); makeSize(n);
this->setSize(n); this->setSize(n);
detail::populateMemForward(data(), n, try {
[&] (void* p) { new (p) value_type(val); } detail::populateMemForward(data(), n,
); [&] (void* p) { new (p) value_type(val); }
);
} catch (...) {
if (this->isExtern()) {
u.freeHeap();
}
throw;
}
} }
// The true_type means we should forward to the size_t,value_type // The true_type means we should forward to the size_t,value_type
......
...@@ -61,6 +61,7 @@ TEST(PackedSyncPtr, Basic) { ...@@ -61,6 +61,7 @@ TEST(PackedSyncPtr, Basic) {
EXPECT_EQ(sp.extra(), 0x13); EXPECT_EQ(sp.extra(), 0x13);
EXPECT_EQ(sp.get(), newP); EXPECT_EQ(sp.get(), newP);
sp.unlock(); sp.unlock();
delete sp.get();
} }
// Here we use the PackedSyncPtr to lock the whole SyncVec (base, *base, and sz) // Here we use the PackedSyncPtr to lock the whole SyncVec (base, *base, and sz)
...@@ -68,6 +69,7 @@ template<typename T> ...@@ -68,6 +69,7 @@ template<typename T>
struct SyncVec { struct SyncVec {
PackedSyncPtr<T> base; PackedSyncPtr<T> base;
SyncVec() { base.init(); } SyncVec() { base.init(); }
~SyncVec() { free(base.get()); }
void push_back(const T& t) { void push_back(const T& t) {
base.set((T*) realloc(base.get(), base.set((T*) realloc(base.get(),
(base.extra() + 1) * sizeof(T))); (base.extra() + 1) * sizeof(T)));
......
...@@ -184,7 +184,7 @@ TEST(ThreadLocal, SimpleRepeatDestructor) { ...@@ -184,7 +184,7 @@ TEST(ThreadLocal, SimpleRepeatDestructor) {
TEST(ThreadLocal, InterleavedDestructors) { TEST(ThreadLocal, InterleavedDestructors) {
Widget::totalVal_ = 0; Widget::totalVal_ = 0;
ThreadLocal<Widget>* w = nullptr; std::unique_ptr<ThreadLocal<Widget>> w;
int wVersion = 0; int wVersion = 0;
const int wVersionMax = 2; const int wVersionMax = 2;
int thIter = 0; int thIter = 0;
...@@ -214,8 +214,7 @@ TEST(ThreadLocal, InterleavedDestructors) { ...@@ -214,8 +214,7 @@ TEST(ThreadLocal, InterleavedDestructors) {
{ {
std::lock_guard<std::mutex> g(lock); std::lock_guard<std::mutex> g(lock);
thIterPrev = thIter; thIterPrev = thIter;
delete w; w.reset(new ThreadLocal<Widget>());
w = new ThreadLocal<Widget>();
++wVersion; ++wVersion;
} }
while (true) { while (true) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment