Skip to content

Avoid setting an empty (null) TraceProvider in trace::Provider::SetTracerProviderΒ #3694

@grrtrr

Description

@grrtrr

Problem Description

By default, the global TracerProvider returns shared pointer to a NoopTracerProvider from trace::Provider::GetTracerProvider(), which has this comment:

// api/include/opentelemetry/trace/provider.h
  /**
   * Returns the singleton TracerProvider.
   *
   * By default, a no-op TracerProvider is returned. This will never return a
   * nullptr TracerProvider.
   */
  static nostd::shared_ptr<TracerProvider> GetTracerProvider() noexcept

The SetTracerProvider allows to set the global singleton instance to a null/empty TracerProvider:

// Similar for empty shared_ptr / unique_ptr:
opentelemetry::trace::Provider::SetTracerProvider(nullptr);

Some of the examples do that to clean up.

While this is fine at the end of a program, when one is sure that there are no more calls to trace::Provider::GetTracerProvider(), this can easily break.

The following segfaults:

opentelemetry::trace::Provider::SetTracerProvider(nullptr);

// ... Many lines below (or in some other file):
auto provider = opentelemetry::trace::Provider::GetTracerProvider();
auto tracer = provider->GetTracer("main");  // <== SEGMENTATION FAULT

Suggestion

Instead of accepting an empty shared_ptr in SetTracerProvider, replace with NoopTracerProvider:

// api/include/opentelemetry/trace/provider.h
  static void SetTracerProvider(const nostd::shared_ptr<TracerProvider> &tp) noexcept
  {
    std::lock_guard<common::SpinLockMutex> guard(GetLock());
    if (!tp) {
        // Ensure that GetTracerProvider never returns a null/empty TracerProvider:
        GetProvider() = std::make_shared<NoopTracerProvider>();
    } else {
        GetProvider() = tp;
    }
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage/acceptedIndicates an issue or PR is ready to be actively worked on.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions