Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions ddtrace/internal/writer/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,11 +503,14 @@ def periodic(self):

def _stop_service(
self,
timeout: Optional[float] = None,
timeout: Optional[float] = 0.1,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the blocking default for writer shutdown

When HTTPWriter.stop() is called without an explicit timeout, this new default makes shutdown wait only 100ms even though the public shutdown contract treats None as “block until flushing has successfully completed.” PeriodicThread.join(timeout) returns silently on timeout, so for slow agentless/HTTP flushes (for example direct AgentlessTraceWriter.stop() or AgentlessTraceWriter.recreate(), which calls self.stop() with no timeout) stop() can mark the service stopped and return while on_shutdown() is still draining or before the process exits, causing queued traces to be dropped or the old writer to run concurrently with the replacement.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pass a timeout from tracer shutdown callers

The main tracer shutdown path still bypasses this default: SpanAggregator.shutdown calls self.writer.stop(timeout) even when the default timeout is None, so HTTPWriter._stop_service receives None and performs the same unbounded join for normal tracer.shutdown()/atexit shutdowns. If this build is meant to test or fix slow writer shutdown through tracer shutdown, the caller needs to supply the 0.1s value or normalize None here; otherwise only direct no-argument writer.stop() calls exercise the new timeout.

Useful? React with 👍 / 👎.

) -> None:
# FIXME: don't join() on stop(), let the caller handle this
super(HTTPWriter, self)._stop_service()
self.join(timeout=timeout)
try:
self.join(timeout=timeout)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Apply the timeout to the actual fork join path

For the fork-timeout bisection, this only bounds the join reached through Service.stop()/_stop_service; the fork hook I checked in ddtrace/internal/threads.py still stops periodic threads with thread._before_fork() and then calls thread.join() with no timeout. In processes that hang while forking with a writer periodic thread active, this build will still block on that unbounded fork join and can incorrectly rule out the writer join hypothesis.

Useful? React with 👍 / 👎.

except Exception:
log.error("Join on periodic thread failed", exc_info=True)

def on_shutdown(self):
try:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "ddtrace"
version = "4.9.1"
version = "4.9.1+jointimeout1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep package version compatible with release tags

If this lands on a releasable branch/tag, the local-version marker cannot pass the existing release/tag gates: .gitlab-ci.yml only treats tags matching vX.Y.Z or vX.Y.ZrcN as releases, while the package version job in .gitlab/package.yml requires CI_COMMIT_TAG to equal v${PACKAGE_VERSION}. With this value, v4.9.1 fails the package-version check and v4.9.1+jointimeout1 does not match the release regex, so release CI cannot proceed from this commit.

Useful? React with 👍 / 👎.

description = "Datadog APM client library"
readme = "README.md"
license = { text = "LICENSE.BSD3" }
Expand Down
Loading