Skip to content

Commit 52c0632

Browse files
fix(profiling): remove use of static C++ [backport 2.7] (#8692)
Backport 0c5b7ea from #8682 to 2.7. libdd_wrapper library needs to strike a balance between using modern (safe) C++ and adhering to the manylinux2014 spec. This is made slightly complicated by the fact that manylinux2014 allows for more recent compilers, so we can emit versioned symbols that rely on e.g., GLIBCXX_3.4.21 when GLIBCXX_3.4.19 is the limit. In my laziness, instead of working around these checks, I just statically-linked libstdc++. As you might guess, this causes symbol visibility issues when end-users have a different c++. In particular, it looks like the Locale portion of std::string destruction hardcodes a `free()` which is invalid in certain other contexts, and it is precisely that operation that gets ODR'd to oblivion. Whoopsies! This patch removes the cases that I saw the emission of GLIBCXX_3.4.21. Moving forward, I'll have to cook up the standard dev apparatus for this. Just to be super clear: since this patch removes statically-linking libstdc++, any defects that arise in sofile generation will be caught by the auditwheel phase of the build pipeline. This fixes #8651 ## Checklist - [x] Change(s) are motivated and described in the PR description - [x] Testing strategy is described if automated tests are not included in the PR - [x] Risks are described (performance impact, potential for breakage, maintainability) - [x] Change is maintainable (easy to change, telemetry, documentation) - [x] [Library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) are followed or label `changelog/no-changelog` is set - [x] Documentation is included (in-code, generated user docs, [public corp docs](https://github.com/DataDog/documentation/)) - [x] Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) - [x] If this PR changes the public interface, I've notified `@DataDog/apm-tees`. - [x] If change touches code that signs or publishes builds or packages, or handles credentials of any kind, I've requested a review from `@DataDog/security-design-and-guidance`. ## Reviewer Checklist - [x] Title is accurate - [x] All changes are related to the pull request's stated goal - [x] Description motivates each change - [x] Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - [x] Testing strategy adequately addresses listed risks - [x] Change is maintainable (easy to change, telemetry, documentation) - [x] Release note makes sense to a user of the library - [x] Author has acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment - [x] Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) Co-authored-by: David Sanchez <[email protected]>
1 parent 8b9f5a0 commit 52c0632

File tree

5 files changed

+29
-36
lines changed

5 files changed

+29
-36
lines changed

ddtrace/internal/datadog/profiling/dd_wrapper/CMakeLists.txt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,8 @@ add_library(dd_wrapper SHARED
3030
# Add common configuration flags
3131
add_ddup_config(dd_wrapper)
3232

33-
# At present, C++17 is chosen as the minimum standard. This conflicts with the
34-
# manylinux2014 standard upon which we must rely. We'll have to statically link
35-
# libstdc++ to avoid this conflict, but need to remain mindful of symbol visibility
36-
# and overall binary size.
3733
target_compile_features(dd_wrapper PUBLIC cxx_std_17)
3834

39-
# Statically link libstdc++ to avoid manylinux2014 conflicts
40-
target_link_options(dd_wrapper PRIVATE -static-libstdc++)
41-
4235
target_include_directories(dd_wrapper PRIVATE
4336
include
4437
${Datadog_INCLUDE_DIRS}

ddtrace/internal/datadog/profiling/dd_wrapper/include/uploader_builder.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <string>
77
#include <string_view>
88
#include <unordered_map>
9+
#include <variant>
910

1011
namespace Datadog {
1112

@@ -40,7 +41,7 @@ class UploaderBuilder
4041
static void set_url(std::string_view _url);
4142
static void set_tag(std::string_view _key, std::string_view _val);
4243

43-
static Uploader build();
44+
static std::variant<Uploader, std::string> build();
4445
};
4546

4647
} // namespace Datadog

ddtrace/internal/datadog/profiling/dd_wrapper/src/interface.cpp

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -269,28 +269,23 @@ ddup_upload()
269269

270270
bool success = false;
271271
{
272-
// The borrow operation takes a reference, then locks the areas where
273-
// the ddog_prof_Profile might be modified. We need to return it
274-
ddog_prof_Profile upload_profile = Datadog::Sample::profile_borrow();
275-
276-
// We create a new uploader just for this operation
277-
try {
278-
auto uploader = Datadog::UploaderBuilder::build();
279-
280-
// NB, upload() cancels any inflight uploads in order to ensure only
281-
// one is active at a time. This simplifies the fork/thread logic.
282-
// This is usually fine, but when the user specifies a profiling
283-
// upload interval less than the upload timeout, we have a potential
284-
// backlog situation which isn't handled. This is against recommended
285-
// practice, but it wouldn't be crazy to add a small backlog queue.
286-
success = uploader.upload(upload_profile);
287-
} catch (const std::exception& e) {
288-
std::cerr << "Failed to create uploader: " << e.what() << std::endl;
289-
}
290-
291-
// We're done with the profile
292-
Datadog::Sample::profile_release();
293-
Datadog::Sample::profile_clear_state();
272+
// There are a few things going on here.
273+
// * profile_borrow takes a reference in a way that locks the areas where the profile might
274+
// be modified. It gets released and cleared after uploading.
275+
// * Uploading cancels inflight uploads. There are better ways to do this, but this is what
276+
// we have for now.
277+
auto uploader = Datadog::UploaderBuilder::build();
278+
struct
279+
{
280+
void operator()(Datadog::Uploader& uploader)
281+
{
282+
uploader.upload(Datadog::Sample::profile_borrow());
283+
Datadog::Sample::profile_release();
284+
Datadog::Sample::profile_clear_state();
285+
}
286+
void operator()(std::string& err) { std::cerr << "Failed to create uploader: " << err << std::endl; }
287+
} visitor;
288+
std::visit(visitor, uploader);
294289
}
295290
return success;
296291
}

ddtrace/internal/datadog/profiling/dd_wrapper/src/uploader_builder.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ join(const std::vector<std::string>& vec, const std::string& delim)
9393
});
9494
}
9595

96-
Uploader
96+
std::variant<Uploader, std::string>
9797
UploaderBuilder::build()
9898
{
9999
// Setup the ddog_Exporter
@@ -130,10 +130,9 @@ UploaderBuilder::build()
130130
}
131131
}
132132

133-
// If any mistakes were made, report on them now and throw
134133
if (!reasons.empty()) {
135134
ddog_Vec_Tag_drop(tags);
136-
throw std::runtime_error("Error initializing exporter, missing or bad configuration: " + join(reasons, ", "));
135+
return "Error initializing exporter, missing or bad configuration: " + join(reasons, ", ");
137136
}
138137

139138
// If we're here, the tags are good, so we can initialize the exporter
@@ -145,10 +144,10 @@ UploaderBuilder::build()
145144
if (res.tag == DDOG_PROF_EXPORTER_NEW_RESULT_OK) {
146145
ddog_exporter = res.ok;
147146
} else {
148-
const std::string errmsg = err_to_msg(&res.err, "Error initializing exporter");
147+
std::string errmsg = err_to_msg(&res.err, "Error initializing exporter");
149148
ddog_Error_drop(&res.err); // errmsg contains a copy of res.err, OK to drop
150-
throw std::runtime_error(errmsg);
149+
return errmsg;
151150
}
152151

153-
return { url, ddog_exporter };
152+
return Uploader{ url, ddog_exporter };
154153
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
profiling: This fixes a ``free(): invalid pointer`` error which would arise as a result of incorrectly
5+
linking the C++ runtime.

0 commit comments

Comments
 (0)