Skip to content

[SDK] Allow context construction failures to propagate - #4703

Merged
marcalff merged 4 commits into
open-telemetry:mainfrom
22elix3r:fix/context-construction-failures-4695
Oct 16, 2026
Merged

marcalff merged 4 commits into
open-telemetry:mainfrom
22elix3r:fix/context-construction-failures-4695

Conversation

@22elix3r

@22elix3r 22elix3r commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #4695

Changes

Remove noexcept from the declarations and definitions of TracerContext, LoggerContext, and MeterContext constructors. These constructors copy resources and, for trace/log contexts, allocate a multi-processor. Failures can now unwind through the already-throwing provider constructors to the caller.

The production diff is only six constructor-signature lines. Runtime GetTracer, GetLogger, and GetMeter remain noexcept.

Add a dedicated allocation-injection executable: runtime tests target resource schema-string copying in all three contexts/providers and internal processor allocation in trace/log contexts. Injection stays out of other tests; CMake excludes the executable for Windows shared-library builds where executable allocation overrides cannot intercept DLL allocations.

Reproduction and verification

On unmodified upstream adebdf0c, each of the six context/provider resource-copy tests aborted with std::bad_alloc instead of reaching its caller's catch block.

With the fix:

  • Full configured suite: 1,120/1,120 CTest cases passed.
  • All eight runtime allocation tests passed under both ABI v1 and v2.
  • ABI-v2 initialization/provider subset: 64/64 passed with metrics exemplar preview enabled.
  • C++14 production syntax checks and C++17 test compilation with exceptions disabled passed.
  • Allocation regression executable passed with AddressSanitizer and leak detection (linked against the normal SDK build).
  • Formatting and diff checks passed; clang-tidy 21 reported only existing warnings in unrelated processor/metrics headers.

CI follow-up

  • Add the missing direct sampler/id-generator includes, and retain <cstddef> explicitly for std::size_t.
  • Keep the test's replacement new/delete implementations out of line on GCC, eliminating the reproduced optimized -Werror=mismatched-new-delete failures without disabling warnings.
  • Set VALGRIND_OPTS only for this Bazel test so its allocation-failure hooks remain active while libc malloc/free are still checked. No tests are skipped.
  • Reproduce the Bazel crash locally under GDB: unwinding a failed string-valued attribute copy crashes in std::variant cleanup. Target the Resource's schema-string copy instead, preserving nonempty attributes and the same constructor-propagation check without also testing that separate cleanup path.

The revised six resource-copy regressions were linked against unmodified adebdf0c: every one still aborted with exit 134. They pass with this PR, so changing the allocation target does not hide the original noexcept bug. This follow-up changes only the test source and its Bazel target; the six-line production constructor fix is unchanged.

Follow-up verification:

  • Full configured suite: 1,120/1,120 passed; all eight allocation tests also passed under ABI v2.
  • GCC 14 -O3 -Werror/maintainer-warning compilation passed for both ABIs; the C++23 GCC 14 Release/maintainer executable passed all eight cases.
  • Both ABI allocation executables passed under Valgrind with zero errors and no leaks; the Bazel target also passed with CI's async/preview flags.
  • Clang Bazel ASan, UBSan, TSan, and no-RTTI configurations passed the target. GCC sanitizer verification was unavailable locally because its ASan runtime file is missing; Clang used its installed runtimes.
  • Local IWYU 0.25 reports correct includes in all three ABI/preview modes; CI uses 0.26. Format, Buildifier, and no-exceptions compilation passed; clang-tidy 21 only reported existing warnings in unchanged headers.
  • Changelog updated
  • Runtime regression tests added
  • Public API reviewed (context constructor exception specifications intentionally relaxed)

Copilot AI balanced review requested due to automatic review settings October 13, 2026 13:29
@22elix3r
22elix3r requested a review from a team as a code owner October 13, 2026 13:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.83%. Comparing base (fc137c6) to head (5b77642).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4703      +/-   ##
==========================================
+ Coverage   86.82%   86.83%   +0.01%     
==========================================
  Files         525      525              
  Lines       20726    20726              
==========================================
+ Hits        17993    17995       +2     
+ Misses       2733     2731       -2     
Files with missing lines Coverage Δ
...k/include/opentelemetry/sdk/trace/tracer_context.h 100.00% <ø> (ø)
sdk/src/logs/logger_context.cc 93.94% <100.00%> (ø)
sdk/src/metrics/meter_context.cc 93.82% <100.00%> (ø)
sdk/src/trace/tracer_context.cc 82.36% <100.00%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Target the resource schema string when injecting copy failures so constructor propagation tests do not also exercise the separately reproduced variant-copy cleanup crash. The revised tests still abort against the original noexcept SDK.

Add direct IWYU dependencies, keep the replacement new/delete out of line for optimized GCC, and preserve their injection hooks under Valgrind with a test-local environment option.

TEST(ProviderInitialization, TracerContextResourceCopyThrows)
{
Resource resource({{"key", true}}, std::string(kResourceValueSize, 'x'));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you help clarify what caused the crash with the original string-valued attribute? Was it an issue with the test setup or with cleanup after the resource copy failed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was cleanup during exception unwinding of the partially constructed resource copy, not initial fixture setup. The source Resource was fully constructed before FailAllocation was enabled. The injected std::bad_alloc occurred while copying the owned string attribute; GDB showed the crash in std::variant cleanup (_Variant_storage / _M_reset / std::__do_visit).

I also reproduced this independently with a standalone std::variant containing the same alternative types, without the SDK or GoogleTest, using GCC 14, GCC 15, and Clang with libstdc++. The partially copied variant had index 255 (the valueless sentinel), but cleanup still entered the visit dispatch and segfaulted. That narrows it to the variant-copy cleanup path rather than the fixture setup.

In 71fe088 the tests instead fail the Resource schema-string copy, while retaining a nonempty attribute map. This isolates context-constructor exception propagation; it does not fix the separate variant cleanup issue. I rechecked all six revised resource-copy cases against unmodified adebdf0: each still aborted with exit 134, whereas with this PR they catch std::bad_alloc.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that answers my question. Targeting the schema-string copy makes sense, especially since the revised tests still catch the original bug.

Let's track the remaining attribute-copy cleanup failure in a separate issue and link it from the test comment. I'm happy to approve this fix independently.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracked separately in #4707, including the SDK-independent reproducer and GCC 14, GCC 15, and Clang-with-libstdc++ results. Linked it from the shared resource-copy test comment in fb55590; the production fix and allocation-injection behavior are unchanged.

@lalitb

lalitb commented Oct 14, 2026

Copy link
Copy Markdown
Member

Thanks for the fix. This lets context construction failures reach the caller instead of terminating. I’ve left one question about the changed test before approving.

Comment thread CHANGELOG.md Outdated
processors shut down their exporters.
[#4686](https://github.com/open-telemetry/opentelemetry-cpp/pull/4686)

* [SDK] Allow allocation failures in tracer, logger, and meter context

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these are public constructors, removing noexcept changes their exception contract and can affect code relying on nothrow construction. Should we mark this as a breaking change in the changelog?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, removing noexcept changes the public exception contract even though this is a bug fix. Done in fb55590: the entry is now under Breaking changes and explicitly notes the impact on code relying on nothrow construction, consistent with #4469.

@marcalff marcalff left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the fix and tests.

@marcalff
marcalff merged commit 69efc51 into open-telemetry:main Oct 16, 2026
84 of 85 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SDK] Provider initialization failures still terminate inside context constructors

4 participants