Skip to content

Commit 97af775

Browse files
committed
Merge branch 'main' into refactor/symdb-cap-uploads-via-ipc
2 parents f0dfc96 + a139e88 commit 97af775

File tree

23 files changed

+349
-85
lines changed

23 files changed

+349
-85
lines changed

.gitlab/testrunner.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
variables:
2-
TESTRUNNER_IMAGE: registry.ddbuild.io/dd-trace-py:v78900213-daaf5b5-testrunner@sha256:bf80b40852537c0eca2d8ace5ffeffa7b916bc4c412bf4a3fce2f9f8d72e7a20
2+
TESTRUNNER_IMAGE: registry.ddbuild.io/dd-trace-py:v81799905-0f9bd8b-testrunner@sha256:f29e49e817cb3fdcc188414b9e94bd9244df7db00b72205738a752ab23953cc5
33

44
.testrunner:
55
image:

ddtrace/appsec/_iast/__init__.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def wrapped_function(wrapped, instance, args, kwargs):
4646
_IAST_TO_BE_LOADED = True
4747
_iast_propagation_enabled = False
4848
_fork_handler_registered = False
49+
_iast_in_pytest_mode = False
4950

5051

5152
def _disable_iast_after_fork():
@@ -87,6 +88,15 @@ def _disable_iast_after_fork():
8788
from ddtrace.appsec._iast._iast_request_context_base import is_iast_request_enabled
8889
from ddtrace.appsec._iast._taint_tracking._context import clear_all_request_context_slots
8990

91+
# In pytest mode, always disable IAST in child processes to avoid segfaults
92+
# when tests create multiprocesses (e.g., for testing fork behavior)
93+
if _iast_in_pytest_mode:
94+
log.debug("IAST fork handler: Pytest mode detected, disabling IAST in child process")
95+
clear_all_request_context_slots()
96+
IAST_CONTEXT.set(None)
97+
asm_config._iast_enabled = False
98+
return
99+
90100
if not is_iast_request_enabled():
91101
# No active context - this is an early fork (web framework worker)
92102
# IAST can be safely initialized fresh in this child process
@@ -168,6 +178,7 @@ def enable_iast_propagation():
168178
"""Add IAST AST patching in the ModuleWatchdog"""
169179
# DEV: These imports are here to avoid _ast.ast_patching import in the top level
170180
# because they are slow and affect serverless startup time
181+
171182
if asm_config._iast_propagation_enabled:
172183
from ddtrace.appsec._iast._ast.ast_patching import _should_iast_patch
173184
from ddtrace.appsec._iast._loader import _exec_iast_patched_module
@@ -183,19 +194,30 @@ def enable_iast_propagation():
183194

184195

185196
def _iast_pytest_activation():
186-
global _iast_propagation_enabled
187-
if _iast_propagation_enabled:
197+
"""Configure IAST settings for pytest execution.
198+
199+
This function sets up IAST configuration but does NOT create a request context.
200+
Request contexts should be created per-test or per-request to avoid threading issues.
201+
202+
Also sets a global flag to indicate we're in pytest mode, which ensures IAST is
203+
disabled in forked child processes to prevent segfaults when tests use multiprocessing.
204+
"""
205+
global _iast_in_pytest_mode
206+
207+
if not asm_config._iast_enabled:
188208
return
189-
os.environ["DD_IAST_ENABLED"] = os.environ.get("DD_IAST_ENABLED") or "1"
209+
210+
# Mark that we're running in pytest mode
211+
# This flag is checked by the fork handler to disable IAST in child processes
212+
_iast_in_pytest_mode = True
213+
190214
os.environ["DD_IAST_REQUEST_SAMPLING"] = os.environ.get("DD_IAST_REQUEST_SAMPLING") or "100.0"
191215
os.environ["_DD_APPSEC_DEDUPLICATION_ENABLED"] = os.environ.get("_DD_APPSEC_DEDUPLICATION_ENABLED") or "false"
192216
os.environ["DD_IAST_VULNERABILITIES_PER_REQUEST"] = os.environ.get("DD_IAST_VULNERABILITIES_PER_REQUEST") or "1000"
193-
os.environ["DD_IAST_MAX_CONCURRENT_REQUESTS"] = os.environ.get("DD_IAST_MAX_CONCURRENT_REQUESTS") or "1000"
194217

195218
asm_config._iast_request_sampling = 100.0
196219
asm_config._deduplication_enabled = False
197220
asm_config._iast_max_vulnerabilities_per_requests = 1000
198-
asm_config._iast_max_concurrent_requests = 1000
199221
oce.reconfigure()
200222

201223

ddtrace/internal/ipc.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,7 @@ class ReadLock(BaseUnixLock):
5757
class WriteLock(BaseUnixLock):
5858
__acquire_mode__ = fcntl.LOCK_EX
5959

60-
@contextmanager
61-
def open_file(path, mode):
62-
yield unpatched_open(path, mode)
60+
open_file = unpatched_open
6361

6462
except ModuleNotFoundError:
6563
# Availability: Windows
@@ -78,7 +76,7 @@ def release(self):
7876

7977
ReadLock = WriteLock = BaseWinLock # type: ignore
8078

81-
def open_file(path, mode):
79+
def open_file(path, mode): # type: ignore
8280
import _winapi
8381

8482
# force all modes to be read/write binary

ddtrace/settings/asm.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ class ASMConfig(DDConfig):
140140
+ r"ey[I-L][\w=-]+\.ey[I-L][\w=-]+(\.[\w.+\/=-]+)?|[\-]{5}BEGIN[a-z\s]+PRIVATE\sKEY"
141141
+ r"[\-]{5}[^\-]+[\-]{5}END[a-z\s]+PRIVATE\sKEY|ssh-rsa\s*[a-z0-9\/\.+]{100,}",
142142
)
143+
# We never use `asm_config._iast_max_concurrent_requests` directly,
144+
# but we define it so it can be reported through telemetry, since it’s used from the C files.
143145
_iast_max_concurrent_requests = DDConfig.var(
144146
int,
145147
IAST.DD_IAST_MAX_CONCURRENT_REQUESTS,

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ services:
185185
# build:
186186
# context: ./docker
187187
# dockerfile: Dockerfile
188-
image: ghcr.io/datadog/dd-trace-py/testrunner:adc7896c0901c0589e45776d9e409c3d1b15cd51@sha256:5fa1b0062e20c753cd5da590df3841b74b9ead5b4531a7ec9f5cacd2b95386e3
188+
image: ghcr.io/datadog/dd-trace-py/testrunner:1717b70091ae646ec3ee29a5cb77158a82209aa3@sha256:aac6cacc68517874da310d5ea78a967f34af8388af5c6621aba77a73c4757657
189189
command: bash
190190
environment:
191191
DD_FAST_BUILD: "1"

lib-injection/sources/requirements.csv

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Dependency,Version Specifier,Python Version
2-
bytecode,>=0.17.0,python_version>='3.14.0'
3-
bytecode,>=0.16.0,python_version>='3.13.0'
4-
bytecode,>=0.15.1,python_version~='3.12.0'
5-
bytecode,>=0.14.0,python_version~='3.11.0'
6-
bytecode,>=0.13.0,python_version<'3.11'
2+
bytecode,">=0.17.0,<1",python_version>='3.14.0'
3+
bytecode,">=0.16.0,<1",python_version>='3.13.0'
4+
bytecode,">=0.15.1,<1",python_version~='3.12.0'
5+
bytecode,">=0.14.0,<1",python_version~='3.11.0'
6+
bytecode,">=0.13.0,<1",python_version<'3.11'
77
envier,~=0.6.1,
88
opentelemetry-api,">=1,<2",
99
wrapt,">=1,<3",

pyproject.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ classifiers = [
3535
"Programming Language :: Python :: 3.14",
3636
]
3737
dependencies = [
38-
"bytecode>=0.17.0; python_version>='3.14.0'",
39-
"bytecode>=0.16.0; python_version>='3.13.0'",
40-
"bytecode>=0.15.1; python_version~='3.12.0'",
41-
"bytecode>=0.14.0; python_version~='3.11.0'",
42-
"bytecode>=0.13.0; python_version<'3.11'",
38+
"bytecode>=0.17.0,<1; python_version>='3.14.0'",
39+
"bytecode>=0.16.0,<1; python_version>='3.13.0'",
40+
"bytecode>=0.15.1,<1; python_version~='3.12.0'",
41+
"bytecode>=0.14.0,<1; python_version~='3.11.0'",
42+
"bytecode>=0.13.0,<1; python_version<'3.11'",
4343
"envier~=0.6.1",
4444
"opentelemetry-api>=1,<2",
4545
"wrapt>=1,<3",
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
Prevent a potential ``ResourceWarning`` in multiprocess scenarios.

requirements.csv

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Dependency,Version Specifier,Python Version
2-
bytecode,>=0.17.0,python_version>='3.14.0'
3-
bytecode,>=0.16.0,python_version>='3.13.0'
4-
bytecode,>=0.15.1,python_version~='3.12.0'
5-
bytecode,>=0.14.0,python_version~='3.11.0'
6-
bytecode,>=0.13.0,python_version<'3.11'
2+
bytecode,">=0.17.0,<1",python_version>='3.14.0'
3+
bytecode,">=0.16.0,<1",python_version>='3.13.0'
4+
bytecode,">=0.15.1,<1",python_version~='3.12.0'
5+
bytecode,">=0.14.0,<1",python_version~='3.11.0'
6+
bytecode,">=0.13.0,<1",python_version<'3.11'
77
envier,~=0.6.1,
88
opentelemetry-api,">=1,<2",
99
wrapt,">=1,<3",

riotfile.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT
544544
env={
545545
"DD_INSTRUMENTATION_TELEMETRY_ENABLED": "0",
546546
"DD_CIVISIBILITY_ITR_ENABLED": "0",
547+
"DD_CIVISIBILITY_EARLY_FLAKE_DETECTION_ENABLED": "0", # DEV: Temporary, remove once merged
547548
},
548549
command="pytest -v {cmdargs} tests/internal/",
549550
pkgs={

0 commit comments

Comments
 (0)