-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix duplicate frees in usingJEMalloc() / usingTCMalloc() checks #1949
Conversation
I'm using folly & jemalloc in one of my projects. After recently updating folly, I was seeing random segfaults in the test suite. With a debug build of jemalloc, I got: ``` <jemalloc>: size mismatch detected (true size 96 vs input size 8), likely caused by application sized deallocation bugs ``` Further debugging and bisecting pointed at commit 73f67d4. The problem is that the new code introduced by that commit does not prevent the slow path from being run multiple times, as was the case with the original code. For some reason, the checks for jemalloc/tcmalloc use a `static` variable for capturing the result of the `malloc` call. If the slow path is executed multiple times, this leads to multiple `free` calls on the same address. I don't know why the variable was made `static`, but it doesn't seem to be necessary and changing the variable to automatic storage duration fixes the issue. (The check for tcmalloc still looks a little questionable as it only looks at the global number of allocated bytes, which also depends on allocations in other threads.)
@Orvid has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
See facebook/folly#1949 for details.
Ping? |
Hey @mhx, long time no see :)
This is unexpected, it definitely should be run only once: note how About why
Agree on this. There is an implicit assumption that the first feature testing will happen before any thread is started, which is almost certainly the case in practice, but it would be better if we didn't need that. |
Hi @ot, hope you're doing fine!
You're absolutely right. I think I missed the I know what's going on, and I believe I missed this when I originally sent the PR:
Here's a simple repro: #include <iostream>
#include <vector>
#include <folly/small_vector.h>
#include <folly/io/IOBuf.h>
int main()
{
folly::small_vector<int, 1> foo;
foo.resize(100);
auto bar = folly::IOBuf::create(42);
std::cout << foo.size() << "\n";
std::cout << bar->goodSize(10) << "\n";
std::vector<void *> ptr;
for (int i = 0; i < 100000; ++i)
{
ptr.push_back(malloc(i % 2000));
}
for (auto p : ptr)
{
free(p);
}
return 0;
} Building folly with cmake/clang like this:
Then compiling the above code in
The C++17 one runs just fine, the C++20 one runs into an assertion during the
They also produce different results for the If you debug into So I can definitely fix this by overriding However, I still think this is an issue as it requires projects using I believe my fix would still be a viable solution, as it would allow the initializer to safely be called more than once.
I'm not sure either, but I genuinely wonder what could justify elision of the |
Even if we work around this specific issue (and it would be a very fragile workaround), compiling with different flags so that different feature flags are applied to the same header is a recipe for ODR violations, and likely to cause more pernicious issues. For example, in general folly makes no guarantees about ABI stability, so you could even have structs with different sizes under different versions of C++. This seems like something that would be best addressed at the build system level. I'm not familiar with our CMake specs, but there should be some way to specify the C++ version from the parent project, and if there isn't we should support that. I'd be very happy to accept a PR in that direction 😃 |
Definitely agree that the standard should be settable and that it's a more robust solution to the problem. I've made a new PR #2005 and will close this one. |
) Summary: This follows up on a discussion in #1949 and the comment by ot that the C++ standard for folly should be (easily) settable by a parent project. There are two commits in this PR: - The first commit removes the redundant `CXX_STD`, which causes `-std=` to be passed to the compiler twice. - The second commit introduces a check before setting `CMAKE_CXX_STANDARD`, so a value set by a parent project won't be overridden. Pull Request resolved: #2005 Reviewed By: Gownta Differential Revision: D47343926 Pulled By: Orvid fbshipit-source-id: a712d117a6d6e2d125ee71f5f8d47ee5ceb3106b
Summary: This follows up on a discussion in facebook/folly#1949 and the comment by ot that the C++ standard for folly should be (easily) settable by a parent project. There are two commits in this PR: - The first commit removes the redundant `CXX_STD`, which causes `-std=` to be passed to the compiler twice. - The second commit introduces a check before setting `CMAKE_CXX_STANDARD`, so a value set by a parent project won't be overridden. X-link: facebook/folly#2005 Reviewed By: Gownta Differential Revision: D47343926 Pulled By: Orvid fbshipit-source-id: a712d117a6d6e2d125ee71f5f8d47ee5ceb3106b
I'm using folly & jemalloc in one of my projects. After recently updating folly, I was seeing random segfaults in the test suite.
With a debug build of jemalloc, I got:
Further debugging and bisecting pointed at commit 73f67d4.
The problem is that the new code introduced by that commit does not prevent the slow path from being run multiple times, as was the case with the original code. For some reason, the checks for jemalloc/tcmalloc use a
static
variable for capturing the result of themalloc
call. If the slow path is executed multiple times, this leads to multiplefree
calls on the same address. I don't know why the variable was madestatic
, but it doesn't seem to be necessary and changing the variable to automatic storage duration fixes the issue.(The check for tcmalloc still looks a little questionable as it only looks at the global number of allocated bytes, which also depends on allocations in other threads.)