Skip to content

Commit 95f764d

Browse files
authored
fix(rc): skip shared memory allocation in AWS Lambda (#17550)
## Summary Fixes the `Unable to create shared memory. Features relying on remote configuration will not work as expected.` warning that appears on every Lambda cold start since ddtrace v4.5.0. Closes DataDog/datadog-lambda-python#785 ## Root Cause The [single RC subscriber refactor](74c3ab43b0) (`v4.5.0`) moved `PublisherSubscriberConnector` creation into `RemoteConfigClient.__init__`, making it eagerly constructed when the module-level `remoteconfig_poller` singleton is instantiated at import time. Before that refactor, connectors were created lazily per-product registration and were never created in Lambda because remote config is disabled there. AWS Lambda does not provide `/dev/shm`, so the `multiprocessing.Array` allocation always fails with `FileNotFoundError`, logging the warning even though: - `DD_REMOTE_CONFIGURATION_ENABLED=false` is set - The ASM settings already disable remote config for Lambda (`asm.py:284`) Both guards run **after** the singleton is already created — too late to prevent the allocation attempt. ## Changes - **`ddtrace/internal/remoteconfig/_connectors.py`**: Check `in_aws_lambda()` in `PublisherSubscriberConnector.__init__` before attempting shared memory allocation. When in Lambda, skip directly to `_DummySharedArray` without logging a warning (this is expected behavior, not an error). - **`tests/internal/remoteconfig/test_remoteconfig_connector.py`**: Add test verifying the connector uses `_DummySharedArray` when `AWS_LAMBDA_FUNCTION_NAME` is set. ## Safety Using `_DummySharedArray` in Lambda is safe because: - `.value` is the only attribute accessed on the shared array — `_DummySharedArray` satisfies the full duck-typing contract - `connector.read()` returns `[]` when `.value` is `b""`, which is handled gracefully by the subscriber dispatch chain (`_dispatch_to_products` calls `periodic()` on callbacks then returns early) - The RC poller never starts in Lambda (`enable()` returns `False`), so no data is ever written to the connector - All RC callbacks (ASM, DI, APM Tracing, Tracer Flare, Feature Flags) handle empty/no-op RC data gracefully - This is the same `_DummySharedArray` already used as the `FileNotFoundError` fallback — we just reach it earlier and without the warning ## Companion PR Defense-in-depth change in datadog-lambda-python: [DataDog/datadog-lambda-python#797](DataDog/datadog-lambda-python#797) (sets `DD_REMOTE_CONFIGURATION_ENABLED=false` before ddtrace loads) ## Test Plan - [ ] Existing `test_remoteconfig_connector.py` tests pass (non-Lambda paths unchanged) - [ ] New `test_connector_uses_dummy_shared_array_in_aws_lambda` test passes - [ ] Verify no `Unable to create shared memory` warning in Lambda cold start logs Co-authored-by: zarir.hamza <zarir.hamza@datadoghq.com>
1 parent 1996620 commit 95f764d

3 files changed

Lines changed: 36 additions & 13 deletions

File tree

ddtrace/internal/remoteconfig/_connectors.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,26 @@ class PublisherSubscriberConnector:
4343
"""
4444

4545
def __init__(self):
46-
try:
47-
self.data = get_mp_context().Array("c", SHARED_MEMORY_SIZE, lock=False)
48-
# FileNotFoundError: /dev/shm may not exist or be inaccessible.
49-
# ImportError: multiprocessing.Array imports multiprocessing.sharedctypes,
50-
# which imports ctypes and requires the _ctypes C extension module. Some
51-
# environments (e.g. Alpine Linux, minimal Docker images, or custom
52-
# Python builds without libffi) do not provide _ctypes and raise
53-
# ModuleNotFoundError.
54-
# See: https://app.datadoghq.com/error-tracking/issue/25b34008-bb9f-11f0-abbd-da7ad0900002
55-
except (FileNotFoundError, ImportError):
56-
log.warning(
57-
"Unable to create shared memory. Features relying on remote configuration will not work as expected."
58-
)
46+
from ddtrace.internal.serverless import in_aws_lambda
47+
48+
if in_aws_lambda():
5949
self.data = _DummySharedArray()
50+
else:
51+
try:
52+
self.data = get_mp_context().Array("c", SHARED_MEMORY_SIZE, lock=False)
53+
# FileNotFoundError: /dev/shm may not exist or be inaccessible.
54+
# ImportError: multiprocessing.Array imports multiprocessing.sharedctypes,
55+
# which imports ctypes and requires the _ctypes C extension module. Some
56+
# environments (e.g. Alpine Linux, minimal Docker images, or custom
57+
# Python builds without libffi) do not provide _ctypes and raise
58+
# ModuleNotFoundError.
59+
# See: https://app.datadoghq.com/error-tracking/issue/25b34008-bb9f-11f0-abbd-da7ad0900002
60+
except (FileNotFoundError, ImportError):
61+
log.warning(
62+
"Unable to create shared memory. "
63+
"Features relying on remote configuration will not work as expected."
64+
)
65+
self.data = _DummySharedArray()
6066
# Checksum attr validates if the Publisher send new data
6167
self.checksum = -1
6268
# shared_data_counter attr validates if the Subscriber send new data
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
fixes:
3+
- |
4+
lambda: Fixes a spurious ``Unable to create shared memory`` warning
5+
on every AWS Lambda cold start.

tests/internal/remoteconfig/test_remoteconfig_connector.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ def test_connector_fallback_on_array_creation_failure():
6868
assert isinstance(connector.data, _DummySharedArray)
6969

7070

71+
def test_connector_uses_dummy_shared_array_in_aws_lambda(monkeypatch):
72+
"""In AWS Lambda, shared memory (/dev/shm) is unavailable. The connector
73+
should skip the allocation attempt entirely and use _DummySharedArray
74+
without logging a warning.
75+
"""
76+
from ddtrace.internal.remoteconfig._connectors import _DummySharedArray
77+
78+
monkeypatch.setenv("AWS_LAMBDA_FUNCTION_NAME", "my-function")
79+
connector = PublisherSubscriberConnector()
80+
assert isinstance(connector.data, _DummySharedArray)
81+
82+
7183
global_connector = PublisherSubscriberConnector()
7284

7385

0 commit comments

Comments
 (0)